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]

Reply via email to