RFR: 8298127: HSS/LMS Signature Verification [v5]
Ferenc Rakoczi
duke at openjdk.org
Mon May 8 13:36:43 UTC 2023
On Thu, 4 May 2023 20:00:18 GMT, Weijun Wang <weijun at openjdk.org> wrote:
>> Ferenc Rakoczi has updated the pull request incrementally with one additional commit since the last revision:
>>
>> adding key translation, finally block, removing 24-byte LMOTS parameters
>
> src/java.base/share/classes/sun/security/provider/HSS.java line 94:
>
>> 92: result &= lmsVerify(lmsPubKey, sig.siglist[sig.Nspk], messageStream.toByteArray());
>> 93: return result;
>> 94: } catch (Exception e) {
>
> If all exceptions thrown are already `SignatureException`, we can let them thrown out instead of returning false. According to the `engineVerify` spec, any problem inside the signature should throw a `SignatureException`. False is returned when the public key cannot verify the exception.
Done.
> src/java.base/share/classes/sun/security/provider/HSS.java line 295:
>
>> 293: int inLen = sigArray.length;
>> 294: if (inLen < 4)
>> 295: throw new InvalidParameterException("Invalid LMS signature");
>
> This is LM-OTS signature. Also, give some explanation. Same on line 301.
Explained.
> src/java.base/share/classes/sun/security/provider/HSS.java line 459:
>
>> 457: final byte[] sigArr;
>> 458:
>> 459: public LMSignature(byte[] sigArray, int offset, boolean checkExactLen) throws InvalidParameterException {
>
> How about we throw a `SignatureException` here. `new HSSSignature` and `new LMOTSignature` all throw it.
Done.
> src/java.base/share/classes/sun/security/provider/HSS.java line 467:
>
>> 465: qArr = Arrays.copyOfRange(sigArray, offset, offset + 4);
>> 466: sigOtsType = LMSUtils.fourBytesToInt(sigArray, offset + 4);
>> 467: LMOTSParams lmotsParams = LMOTSParams.of(sigOtsType);
>
> Catch `IllegalArgumentException` here and rethrow a `SignatureException`. Same on line 482.
Done.
> src/java.base/share/classes/sun/security/provider/HSS.java line 659:
>
>> 657: }
>> 658: public byte[] lmotsPubKeyCandidate(LMSignature lmSig, byte[] message, LMSPublicKey pKey)
>> 659: throws NoSuchAlgorithmException, DigestException {
>
> `DigestException` should not happen because we allocate all the buffer ourselves. `NoSuchAlgorithmException` should not happen because we should have all the algorithms. If they do happen, that's not user problem at all. I think the usual way is to wrap them into a `ProviderException`. This is also true in `lmsVerify()`.
Done.
> src/java.base/share/classes/sun/security/provider/HSS.java line 662:
>
>> 660: LMOTSignature lmOtSig = lmSig.lmotSig;
>> 661: if (lmOtSig.otSigType != pKey.otsType) {
>> 662: throw new IllegalArgumentException("OTS public key type and OTS signature type do not match");
>
> I'd rather throw `SignatureException`. This method is actually verifying an LM-OTS signature, right? Avoid using unchecked exceptions instead of `ProviderException` unless you can be sure they are caught nicely.
Changed.
> src/java.base/share/classes/sun/security/provider/HSS.java line 736:
>
>> 734: }
>> 735: }
>> 736: throw new InvalidKeySpecException();
>
> Give an error message. Try look at what other factories are doing. Same for lines 751, 768, 727, 44, 49, and 57.
Added explanations.
> src/java.base/share/classes/sun/security/provider/HSS.java line 745:
>
>> 743:
>> 744: @Override
>> 745: protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec) throws InvalidKeySpecException {
>
> Usually when `key` is null an `InvalidKeySpecException` is thrown. Here it's an NPE.
Done.
> src/java.base/share/classes/sun/security/provider/HSS.java line 809:
>
>> 807: HSSSignature(byte[] sigArr, int pubKeyL, String pubKeyHashAlg) throws SignatureException {
>> 808: if (sigArr.length < 4) {
>> 809: throw new SignatureException("Bad HSS signature");
>
> Maybe you can say why it is bad. This also applies to "Invalid HSS public key", "Invalid LMS signature" and "Invalid LMS public key" messages.
Done.
> src/java.base/share/classes/sun/security/provider/HSS.java line 823:
>
>> 821: index += siglist[i].sigArrayLength();
>> 822: pubList[i] = new LMSPublicKey(sigArr, index, false);
>> 823: if (!pubList[i].getDigestAlgorithm().equals(pubKeyHashAlg)) {
>
> Comparing hash algorithm is not enough. Length (`m`) should also be compared.
Compared.
> src/java.base/share/classes/sun/security/provider/HSS.java line 829:
>
>> 827: }
>> 828: siglist[Nspk] = new LMSignature(sigArr, index, true);
>> 829: } catch (Exception E) {
>
> The `SignatureException` thrown on line 824 does not need to be wrapped into another `SignatureException`. Maybe just catch `InvalidKeyException` (if you throw `SignatureException` in `new LMSSignature`).
Done.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187452891
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187453204
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187453062
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187453398
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187452980
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187453253
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187453292
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187452998
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187453109
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187453175
PR Review Comment: https://git.openjdk.org/jdk/pull/13691#discussion_r1187452934
More information about the security-dev
mailing list