@@ -1165,5 +1165,195 @@ public void testRSAPSSParametersInitWithUnsupportedFormat()
11651165 /* expected */
11661166 }
11671167 }
1168+
1169+ /**
1170+ * Test that PSS parameters can be decoded when the hash
1171+ * AlgorithmIdentifier has absent parameters (no NULL).
1172+ *
1173+ * Per RFC 4055 Section 2.1, hash AlgorithmIdentifiers can have either:
1174+ * - Absent parameters (SHOULD per RFC)
1175+ * - NULL parameters (for backwards compatibility)
1176+ *
1177+ * This test verifies we correctly handle the absent parameters case
1178+ * which is the preferred encoding per RFC 4055.
1179+ */
1180+ @ Test
1181+ public void testRSAPSSParametersDecodingWithAbsentHashParams ()
1182+ throws Exception {
1183+
1184+ /*
1185+ * Manually constructed DER encoding of PSS parameters with SHA-256
1186+ * hash AlgorithmIdentifier that has ABSENT parameters (no NULL).
1187+ *
1188+ * RSASSA-PSS-params ::= SEQUENCE {
1189+ * hashAlgorithm [0] HashAlgorithm DEFAULT sha1,
1190+ * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
1191+ * saltLength [2] INTEGER DEFAULT 20,
1192+ * trailerField [3] INTEGER DEFAULT 1
1193+ * }
1194+ *
1195+ * HashAlgorithm ::= AlgorithmIdentifier
1196+ * AlgorithmIdentifier ::= SEQUENCE {
1197+ * algorithm OBJECT IDENTIFIER,
1198+ * parameters ANY DEFINED BY algorithm OPTIONAL
1199+ * }
1200+ *
1201+ * This encoding has:
1202+ * - [0] hashAlgorithm: SHA-256 with ABSENT parameters
1203+ * - [1] maskGenAlgorithm: MGF1 with SHA-256 (also with absent params)
1204+ * - [2] saltLength: 32
1205+ *
1206+ * Structure breakdown:
1207+ * 30 30 ; SEQUENCE (48 bytes)
1208+ * A0 0D ; [0] context tag (13 bytes)
1209+ * 30 0B ; SEQUENCE (11 bytes) - AlgId
1210+ * 06 09 ; OID (9 bytes)
1211+ * 60 86 48 01 65 03 04 02 01 ; SHA-256 OID
1212+ * -- NOTE: no NULL here (absent parameters)
1213+ * A1 1A ; [1] context tag (26 bytes)
1214+ * 30 18 ; SEQUENCE (24 bytes) - MGF1 AlgId
1215+ * 06 09 ; OID (9 bytes)
1216+ * 2A 86 48 86 F7 0D 01 01 08 ; MGF1 OID
1217+ * 30 0B ; SEQUENCE (11 bytes) - Hash AlgId
1218+ * 06 09 ; OID (9 bytes)
1219+ * 60 86 48 01 65 03 04 02 01 ; SHA-256 OID
1220+ * -- NOTE: no NULL here (absent parameters)
1221+ * A2 03 ; [2] context tag (3 bytes)
1222+ * 02 01 20 ; INTEGER 32 (salt length)
1223+ */
1224+ byte [] pssParamsAbsentHashParams = new byte [] {
1225+ 0x30 , 0x30 , /* SEQUENCE 48 */
1226+ (byte )0xA0 , 0x0D , /* [0] 13 */
1227+ 0x30 , 0x0B , /* SEQUENCE 11 */
1228+ 0x06 , 0x09 , /* OID 9 */
1229+ 0x60 , (byte )0x86 , 0x48 , 0x01 , 0x65 ,
1230+ 0x03 , 0x04 , 0x02 , 0x01 , /* SHA-256 */
1231+ /* NO NULL - absent parameters */
1232+ (byte )0xA1 , 0x1A , /* [1] 26 */
1233+ 0x30 , 0x18 , /* SEQUENCE 24 */
1234+ 0x06 , 0x09 , /* OID 9 */
1235+ 0x2A , (byte )0x86 , 0x48 , (byte )0x86 ,
1236+ (byte )0xF7 , 0x0D , 0x01 , 0x01 , 0x08 , /* MGF1 */
1237+ 0x30 , 0x0B , /* SEQUENCE 11 */
1238+ 0x06 , 0x09 , /* OID 9 */
1239+ 0x60 , (byte )0x86 , 0x48 , 0x01 ,
1240+ 0x65 , 0x03 , 0x04 , 0x02 , 0x01 , /* SHA-256 */
1241+ /* NO NULL - absent parameters */
1242+ (byte )0xA2 , 0x03 , /* [2] 3 */
1243+ 0x02 , 0x01 , 0x20 /* INTEGER 32 */
1244+ };
1245+
1246+ /* Should not throw an exception, absent params are valid */
1247+ AlgorithmParameters params =
1248+ AlgorithmParameters .getInstance ("RSASSA-PSS" , "wolfJCE" );
1249+ params .init (pssParamsAbsentHashParams );
1250+
1251+ /* Verify parameters were decoded correctly */
1252+ PSSParameterSpec spec =
1253+ params .getParameterSpec (PSSParameterSpec .class );
1254+ assertNotNull (spec );
1255+ assertEquals ("SHA-256" , spec .getDigestAlgorithm ());
1256+ assertEquals ("MGF1" , spec .getMGFAlgorithm ());
1257+ assertEquals (32 , spec .getSaltLength ());
1258+ assertEquals (1 , spec .getTrailerField ());
1259+
1260+ /* Verify MGF1 hash algorithm */
1261+ assertTrue (
1262+ spec .getMGFParameters () instanceof MGF1ParameterSpec );
1263+ MGF1ParameterSpec mgf1Spec =
1264+ (MGF1ParameterSpec ) spec .getMGFParameters ();
1265+ assertEquals ("SHA-256" , mgf1Spec .getDigestAlgorithm ());
1266+ }
1267+
1268+ /**
1269+ * Test that PSS parameters with both absent and NULL parameters
1270+ * produce equivalent results.
1271+ */
1272+ @ Test
1273+ public void testRSAPSSParametersAbsentVsNullParams ()
1274+ throws Exception {
1275+
1276+ /*
1277+ * PSS params with SHA-256 and NULL parameters in AlgorithmIdentifier.
1278+ */
1279+ byte [] pssParamsWithNull = new byte [] {
1280+ 0x30 , 0x34 , /* SEQUENCE 52 */
1281+ (byte )0xA0 , 0x0F , /* [0] 15 */
1282+ 0x30 , 0x0D , /* SEQUENCE 13 */
1283+ 0x06 , 0x09 , /* OID 9 */
1284+ 0x60 , (byte )0x86 , 0x48 , 0x01 , 0x65 ,
1285+ 0x03 , 0x04 , 0x02 , 0x01 , /* SHA-256 */
1286+ 0x05 , 0x00 , /* NULL */
1287+ (byte )0xA1 , 0x1C , /* [1] 28 */
1288+ 0x30 , 0x1A , /* SEQUENCE 26 */
1289+ 0x06 , 0x09 , /* OID 9 */
1290+ 0x2A , (byte )0x86 , 0x48 , (byte )0x86 ,
1291+ (byte )0xF7 , 0x0D , 0x01 , 0x01 , 0x08 , /* MGF1 */
1292+ 0x30 , 0x0D , /* SEQUENCE 13 */
1293+ 0x06 , 0x09 , /* OID 9 */
1294+ 0x60 , (byte )0x86 , 0x48 , 0x01 ,
1295+ 0x65 , 0x03 , 0x04 , 0x02 , 0x01 , /* SHA-256 */
1296+ 0x05 , 0x00 , /* NULL */
1297+ (byte )0xA2 , 0x03 , /* [2] 3 */
1298+ 0x02 , 0x01 , 0x20 /* INTEGER 32 */
1299+ };
1300+
1301+ /*
1302+ * PSS params with SHA-256 and ABSENT parameters in AlgorithmIdentifier.
1303+ */
1304+ byte [] pssParamsAbsent = new byte [] {
1305+ 0x30 , 0x30 , /* SEQUENCE 48 */
1306+ (byte )0xA0 , 0x0D , /* [0] 13 */
1307+ 0x30 , 0x0B , /* SEQUENCE 11 */
1308+ 0x06 , 0x09 , /* OID 9 */
1309+ 0x60 , (byte )0x86 , 0x48 , 0x01 , 0x65 ,
1310+ 0x03 , 0x04 , 0x02 , 0x01 , /* SHA-256 */
1311+ /* NO NULL - absent parameters */
1312+ (byte )0xA1 , 0x1A , /* [1] 26 */
1313+ 0x30 , 0x18 , /* SEQUENCE 24 */
1314+ 0x06 , 0x09 , /* OID 9 */
1315+ 0x2A , (byte )0x86 , 0x48 , (byte )0x86 ,
1316+ (byte )0xF7 , 0x0D , 0x01 , 0x01 , 0x08 , /* MGF1 */
1317+ 0x30 , 0x0B , /* SEQUENCE 11 */
1318+ 0x06 , 0x09 , /* OID 9 */
1319+ 0x60 , (byte )0x86 , 0x48 , 0x01 ,
1320+ 0x65 , 0x03 , 0x04 , 0x02 , 0x01 , /* SHA-256 */
1321+ /* NO NULL - absent parameters */
1322+ (byte )0xA2 , 0x03 , /* [2] 3 */
1323+ 0x02 , 0x01 , 0x20 /* INTEGER 32 */
1324+ };
1325+
1326+ /* Decode both encodings */
1327+ AlgorithmParameters paramsWithNull =
1328+ AlgorithmParameters .getInstance ("RSASSA-PSS" , "wolfJCE" );
1329+ paramsWithNull .init (pssParamsWithNull );
1330+
1331+ AlgorithmParameters paramsAbsent =
1332+ AlgorithmParameters .getInstance ("RSASSA-PSS" , "wolfJCE" );
1333+ paramsAbsent .init (pssParamsAbsent );
1334+
1335+ /* Get specs from both */
1336+ PSSParameterSpec specWithNull =
1337+ paramsWithNull .getParameterSpec (PSSParameterSpec .class );
1338+ PSSParameterSpec specAbsent =
1339+ paramsAbsent .getParameterSpec (PSSParameterSpec .class );
1340+
1341+ /* Both should decode to equivalent parameters */
1342+ assertEquals (specWithNull .getDigestAlgorithm (),
1343+ specAbsent .getDigestAlgorithm ());
1344+ assertEquals (specWithNull .getMGFAlgorithm (),
1345+ specAbsent .getMGFAlgorithm ());
1346+ assertEquals (specWithNull .getSaltLength (),
1347+ specAbsent .getSaltLength ());
1348+ assertEquals (specWithNull .getTrailerField (),
1349+ specAbsent .getTrailerField ());
1350+
1351+ MGF1ParameterSpec mgf1WithNull =
1352+ (MGF1ParameterSpec ) specWithNull .getMGFParameters ();
1353+ MGF1ParameterSpec mgf1Absent =
1354+ (MGF1ParameterSpec ) specAbsent .getMGFParameters ();
1355+ assertEquals (mgf1WithNull .getDigestAlgorithm (),
1356+ mgf1Absent .getDigestAlgorithm ());
1357+ }
11681358}
11691359
0 commit comments