This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push:
new 55d2fa3150 Correct regression in fix for BZ 67675 - allow for default
PRF
55d2fa3150 is described below
commit 55d2fa315032d029fa76e0af73ef60f81f7bc4a4
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Dec 14 16:09:01 2023 +0000
Correct regression in fix for BZ 67675 - allow for default PRF
https://bz.apache.org/bugzilla/show_bug.cgi?id=67675#c24
---
java/org/apache/tomcat/util/buf/Asn1Parser.java | 41 +++++++++++++-
java/org/apache/tomcat/util/net/jsse/PEMFile.java | 65 +++++++++++++---------
.../apache/tomcat/util/net/jsse/TestPEMFile.java | 7 +++
...ncrypted-pkcs8-hmacsha1default-des-ede3-cbc.pem | 54 ++++++++++++++++++
webapps/docs/changelog.xml | 6 ++
5 files changed, 146 insertions(+), 27 deletions(-)
diff --git a/java/org/apache/tomcat/util/buf/Asn1Parser.java
b/java/org/apache/tomcat/util/buf/Asn1Parser.java
index 92d13c02a8..1d88b113d4 100644
--- a/java/org/apache/tomcat/util/buf/Asn1Parser.java
+++ b/java/org/apache/tomcat/util/buf/Asn1Parser.java
@@ -17,6 +17,8 @@
package org.apache.tomcat.util.buf;
import java.math.BigInteger;
+import java.util.ArrayDeque;
+import java.util.Deque;
import org.apache.tomcat.util.res.StringManager;
@@ -24,7 +26,7 @@ import org.apache.tomcat.util.res.StringManager;
* This is a very basic ASN.1 parser that provides the limited functionality
required by Tomcat. It is a long way from a
* complete parser.
* <p>
- * TODO: Consider extending this parser and refactoring the SpnegoTokenFixer
to use it.
+ * TODO: Consider extending/re-writing this parser and refactoring the
SpnegoTokenFixer to use it.
*/
public class Asn1Parser {
@@ -41,6 +43,15 @@ public class Asn1Parser {
private int pos = 0;
+ /*
+ * This is somewhat of a hack to work around the simplified design of the
parsing API that could result in ambiguous
+ * results when nested sequences were optional. Checking the current
nesting level of sequence tags enables a user
+ * of the parser to determine if an optional sequence is present or not.
+ *
+ * See https://bz.apache.org/bugzilla/show_bug.cgi?id=67675#c24
+ */
+ private Deque<Integer> nestedSequenceEndPositions = new ArrayDeque<>();
+
public Asn1Parser(byte[] source) {
this.source = source;
@@ -58,7 +69,21 @@ public class Asn1Parser {
public void parseTagSequence() {
+ /*
+ * Check to see if the parser has completely parsed, based on end
position for the sequence, any previous
+ * sequences and remove those sequences from the sequence nesting
tracking mechanism if they have been
+ * completely parsed.
+ */
+ while (nestedSequenceEndPositions.size() > 0) {
+ if (nestedSequenceEndPositions.peekLast().intValue() <= pos) {
+ nestedSequenceEndPositions.pollLast();
+ } else {
+ break;
+ }
+ }
+ // Add the new sequence to the sequence nesting tracking mechanism.
parseTag(TAG_SEQUENCE);
+ nestedSequenceEndPositions.addLast(Integer.valueOf(-1));
}
@@ -90,6 +115,15 @@ public class Asn1Parser {
len = len + next();
}
}
+ /*
+ * If this is the first length parsed after a sequence has been added
to the sequence nesting tracking mechansim
+ * it must be the length of the sequence so update the entry to record
the end position of the sequence. Note
+ * that position recorded is actually the start of the first element
after the sequence ends.
+ */
+ if (nestedSequenceEndPositions.peekLast() != null &&
nestedSequenceEndPositions.peekLast().intValue() == -1) {
+ nestedSequenceEndPositions.pollLast();
+ nestedSequenceEndPositions.addLast(Integer.valueOf(pos + len));
+ }
return len;
}
@@ -139,4 +173,9 @@ public class Asn1Parser {
private int next() {
return source[pos++] & 0xFF;
}
+
+
+ public int getNestedSequenceLevel() {
+ return nestedSequenceEndPositions.size();
+ }
}
diff --git a/java/org/apache/tomcat/util/net/jsse/PEMFile.java
b/java/org/apache/tomcat/util/net/jsse/PEMFile.java
index 2499beda79..a05ae6fdc6 100644
--- a/java/org/apache/tomcat/util/net/jsse/PEMFile.java
+++ b/java/org/apache/tomcat/util/net/jsse/PEMFile.java
@@ -75,10 +75,13 @@ public class PEMFile {
private static final byte[] OID_PBKDF2 =
new byte[] { 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7,
0x0D, 0x01, 0x05, 0x0C };
+ // Default defined in RFC 8018
+ private static final String DEFAULT_PRF = "HmacSHA1";
+
private static final Map<String,String> OID_TO_PRF = new HashMap<>();
static {
// 1.2.840.113549.2.7
- OID_TO_PRF.put("2a864886f70d0207", "HmacSHA1");
+ OID_TO_PRF.put("2a864886f70d0207", DEFAULT_PRF);
// 1.2.840.113549.2.8
OID_TO_PRF.put("2a864886f70d0208", "HmacSHA224");
// 1.2.840.113549.2.9
@@ -337,25 +340,26 @@ public class PEMFile {
//@formatter:off
/*
* RFC 5208 - PKCS #8
- * RFC 8108 - PKCS #5
+ * RFC 8018 - PKCS #5
*
- * SEQ - PKCS #8
- * SEQ - PKCS #8 encryptionAlgorithm
- * OID - PKCS #5 PBES2 OID
- * SEQ - PKCS #5 PBES2-params
- * SEQ - PKCS #5 PBES2 key derivation
function
- * OID - PKCS #5 PBES2 KDF OID - must
be PBKDF2
- * SEQ - PKCS #5 PBKDF2-params
- * OCTET STRING - PKCS #5 PBKDF2 salt
- * INT - PKCS #5 PBKDF2 interationCount
- * INT - PKCS #5 PBKDF2 key length
OPTIONAL
- * SEQ - PKCS #5 PBKDF2 PRF
- * OID - PKCS #5 PBKDF2 PRF OID
- * NULL - PKCS #5 PBKDF2 PRF parameters
- * SEQ - PKCS #5 PBES2 encryption scheme
- * OID - PKCS #5 PBES2 algorithm OID
- * OCTET STRING - PKCS #5 PBES2 algorithm iv
- * OCTET STRING - PKCS #8 encryptedData
+ * Nesting
+ * SEQ 1 - PKCS #8
+ * SEQ 2 - PKCS #8 encryptionAlgorithm
+ * OID - PKCS #5 PBES2 OID
+ * SEQ 3 - PKCS #5 PBES2-params
+ * SEQ 4 - PKCS #5 PBES2 key derivation
function
+ * OID - PKCS #5 PBES2 KDF OID - must
be PBKDF2
+ * SEQ 5 - PKCS #5 PBKDF2-params
+ * OCTET STRING - PKCS #5 PBKDF2 salt
+ * INT - PKCS #5 PBKDF2
interationCount
+ * INT - PKCS #5 PBKDF2 key length
OPTIONAL
+ * SEQ 6 - PKCS #5 PBKDF2 PRF defaults
to HmacSHA1 if not present
+ * OID - PKCS #5 PBKDF2 PRF OID
+ * NULL - PKCS #5 PBKDF2 PRF parameters
+ * SEQ 4 - PKCS #5 PBES2 encryption
scheme
+ * OID - PKCS #5 PBES2 algorithm OID
+ * OCTET STRING - PKCS #5 PBES2 algorithm iv
+ * OCTET STRING - PKCS #8 encryptedData
*/
//@formatter:on
@@ -403,16 +407,25 @@ public class PEMFile {
// PBKDF2 PRF
p.parseTagSequence();
p.parseLength();
- byte[] oidPRF = p.parseOIDAsBytes();
- String prf = OID_TO_PRF.get(HexUtils.toHexString(oidPRF));
- if (prf == null) {
- throw new
NoSuchAlgorithmException(sm.getString("pemFile.unknownPrfAlgorithm",
toDottedOidString(oidPRF)));
+ String prf = null;
+ // This tag is optional. If present the nested sequence
level will be 6 else if will be 4.
+ if (p.getNestedSequenceLevel() == 6) {
+ byte[] oidPRF = p.parseOIDAsBytes();
+ prf = OID_TO_PRF.get(HexUtils.toHexString(oidPRF));
+ if (prf == null) {
+ throw new
NoSuchAlgorithmException(sm.getString("pemFile.unknownPrfAlgorithm",
toDottedOidString(oidPRF)));
+ }
+ p.parseNull();
+
+ // Read the sequence tag for the PBES2 encryption
scheme
+ p.parseTagSequence();
+ p.parseLength();
+ } else {
+ // Use the default
+ prf = DEFAULT_PRF;
}
- p.parseNull();
// PBES2 encryption scheme
- p.parseTagSequence();
- p.parseLength();
byte[] oidCipher = p.parseOIDAsBytes();
Algorithm algorithm =
OID_TO_ALGORITHM.get(HexUtils.toHexString(oidCipher));
if (algorithm == null) {
diff --git a/test/org/apache/tomcat/util/net/jsse/TestPEMFile.java
b/test/org/apache/tomcat/util/net/jsse/TestPEMFile.java
index 61a375be46..b62b253a02 100644
--- a/test/org/apache/tomcat/util/net/jsse/TestPEMFile.java
+++ b/test/org/apache/tomcat/util/net/jsse/TestPEMFile.java
@@ -39,6 +39,7 @@ public class TestPEMFile {
private static final String KEY_ENCRYPTED_PKCS1_DES_CBC =
"key-encrypted-pkcs1-des-cbc.pem";
private static final String KEY_ENCRYPTED_PKCS1_DES_EDE3_CBC =
"key-encrypted-pkcs1-des-ede3-cbc.pem";
private static final String KEY_ENCRYPTED_PKCS1_AES256 =
"key-encrypted-pkcs1-aes256.pem";
+ private static final String
KEY_ENCRYPTED_PKCS8_HMACSHA1DEFAULT_DES_EDE3_CBC =
"key-encrypted-pkcs8-hmacsha1default-des-ede3-cbc.pem";
private static final String KEY_ENCRYPTED_PKCS8_HMACSHA256_AES_128_CBC =
"key-encrypted-pkcs8-hmacsha256-aes-128-cbc.pem";
private static final String KEY_ENCRYPTED_PKCS8_HMACSHA256_AES_256_CBC =
"key-encrypted-pkcs8-hmacsha256-aes-256-cbc.pem";
private static final String KEY_ENCRYPTED_PKCS8_HMACSHA256_DES_EDE3_CBC =
"key-encrypted-pkcs8-hmacsha256-des-ede3-cbc.pem";
@@ -92,6 +93,12 @@ public class TestPEMFile {
}
+ @Test
+ public void testKeyEncryptedPkcs8HmacSha1DefaultDesEde3Cbc() throws
Exception {
+ testKeyEncrypted(KEY_ENCRYPTED_PKCS8_HMACSHA1DEFAULT_DES_EDE3_CBC);
+ }
+
+
@Test
public void testKeyEncryptedPkcs8HmacSha256Aes128() throws Exception {
testKeyEncrypted(KEY_ENCRYPTED_PKCS8_HMACSHA256_AES_128_CBC);
diff --git
a/test/org/apache/tomcat/util/net/jsse/key-encrypted-pkcs8-hmacsha1default-des-ede3-cbc.pem
b/test/org/apache/tomcat/util/net/jsse/key-encrypted-pkcs8-hmacsha1default-des-ede3-cbc.pem
new file mode 100755
index 0000000000..8dbbe78871
--- /dev/null
+++
b/test/org/apache/tomcat/util/net/jsse/key-encrypted-pkcs8-hmacsha1default-des-ede3-cbc.pem
@@ -0,0 +1,54 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+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
+dmk=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 182eae7287..5ff80c4337 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -112,6 +112,12 @@
by the NIO2 connector which was using platform threads even when
configured to use virtual threads. (markt)
</fix>
+ <fix>
+ Correct a regression in the fix for <bug>67675</bug> that broke TLS key
+ file parsing for PKCS#8 format keys that do not specify an explicit
+ pseudo-random function and rely on the default. This typically affects
+ keys generated by OpenSSL 1.0.2. (markt)
+ </fix>
</changelog>
</subsection>
</section>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]