bcgit / bc-java

Bouncy Castle Java Distribution (Mirror)
https://www.bouncycastle.org/java.html
MIT License
2.27k stars 1.12k forks source link

Public key parameter digestParamSet should be optional for GOST 34.10 R 2012 #1586

Closed mugz3m closed 5 months ago

mugz3m commented 6 months ago

Environment

Description

  1. When generating a certificate using the GOST 34.10 R 2012 algorithm with a key length of 256 and parameters id-tc26-gost-3410-2012-256-paramSetB via Bouncy Castle we have two parameters in the parameters field of the SubjectPublicKeyInfo structure:

    • publicKeyParamSet: 1.2.643.7.1.2.1.1.2 equal to id-tc26-gost-3410-12-256-paramSetB;
    • digestParamSet: 1.2.643.7.1.1.2.2 equal to id-tc26-gost3411-12-256.
  2. On verifying a CMS GOST 34.10 R 2012 signature with only one parameter publicKeyParamSet equal to id-tc26-gost-3410-12-256-paramSetB in the parameters field of the certificate's SubjectPublicKeyInfo ArrayIndexOutOfBoundsException exception is thrown as Bouncy Castle ALWAYS expects at least two parameters to be present: publicKeyParamSet and digestParamSet.

    Stacktrace:

    java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
    at org.bouncycastle.asn1.ASN1Sequence.getObjectAt(ASN1Sequence.java:269)
    at org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters.<init>(GOST3410PublicKeyAlgParameters.java:64)
    at org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters.getInstance(GOST3410PublicKeyAlgParameters.java:35)
    at org.bouncycastle.jcajce.provider.asymmetric.ecgost12.BCECGOST3410_2012PublicKey.populateFromPubKeyInfo(BCECGOST3410_2012PublicKey.java:220)
    at org.bouncycastle.jcajce.provider.asymmetric.ecgost12.BCECGOST3410_2012PublicKey.<init>(BCECGOST3410_2012PublicKey.java:183)
    at org.bouncycastle.jcajce.provider.asymmetric.ecgost12.KeyFactorySpi.generatePublic(KeyFactorySpi.java:159)
    at org.bouncycastle.jce.provider.BouncyCastleProvider.getPublicKey(BouncyCastleProvider.java:530)
    at org.bouncycastle.jcajce.provider.asymmetric.x509.X509CertificateImpl.getPublicKey(X509CertificateImpl.java:450)
    at org.bouncycastle.jcajce.provider.asymmetric.x509.X509CertificateObject.getPublicKey(X509CertificateObject.java:96)
    at org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder$1.get(JcaContentVerifierProviderBuilder.java:101)
    at org.bouncycastle.cms.SignerInformationVerifier.getContentVerifier(SignerInformationVerifier.java:43)
    at org.bouncycastle.cms.SignerInformation.doVerify(SignerInformation.java:364)
    at org.bouncycastle.cms.SignerInformation.verify(SignerInformation.java:659)
    at org.example.CmsSignVerifyDetachedGOSTR3410_2012_256.verifyDetached(CmsSignVerifyDetachedGOSTR3410_2012_256.java:98)
    at org.example.CmsSignVerifyDetachedGOSTR3410_2012_256.main(CmsSignVerifyDetachedGOSTR3410_2012_256.java:60)
    java.lang.RuntimeException: Detached CMS signature is invalid
    at org.example.CmsSignVerifyDetachedGOSTR3410_2012_256.main(CmsSignVerifyDetachedGOSTR3410_2012_256.java:63)

Class GOST3410PublicKeyAlgParameters.java requires digestParamSet parameter in it's constructors or expects that ASN1Sequence parameter must always have an object at the index 1 indicating digestParamSet.

The library's current behavior doesn't comply with RFC 9215. According to section 4.2:

The digestParamSet field:

  • SHOULD be omitted if the GOST R 34.10-2012 signature algorithm is used with a 512-bit key length

  • MUST be present and must be equal to id-tc26-digest- gost3411-12-256 if one of the following values is used as publicKeyParamSet:

    • id-GostR3410-2001-TestParamSet

    • id-GostR3410-2001-CryptoPro-A-ParamSet

    • id-GostR3410-2001-CryptoPro-B-ParamSet

    • id-GostR3410-2001-CryptoPro-C-ParamSet

    • id-GostR3410-2001-CryptoPro-XchA-ParamSet

    • id-GostR3410-2001-CryptoPro-XchB-ParamSet

  • SHOULD be omitted if publicKeyParamSet is equal to:

    • id-tc26-gost-3410-2012-256-paramSetA
  • MUST be omitted if one of the following values is used as publicKeyParamSet:

    • id-tc26-gost-3410-2012-256-paramSetB

    • id-tc26-gost-3410-2012-256-paramSetC

    • id-tc26-gost-3410-2012-256-paramSetD

Expected behavior

The expected behavior in this case is that Bouncy Castle supports the conditions described in section 4.2 of RFC 9215:

  1. Verification of CMS GOST 34.10 R 2012 signature without digestParamSet parameter in certificate's SubjectPublicKeyInfo should not throw exception.

  2. Objects generated via Bouncy Castle using the GOST 34.10 R 2012 algorithm with a key length of 256 bits and a value publicKeyParamSet equal to:

    • id-tc26-gost-3410-2012-256-paramSetB
    • id-tc26-gost-3410-2012-256-paramSetC
    • id-tc26-gost-3410-2012-256-paramSetD

    must have only one parameter publicKeyParamSet in parameters. The digestParamSet parameter should be omitted.

Link to samples

https://drive.google.com/file/d/1Zyo8qcPF-LCBGMNEXRANgr22KGKH4NwX/view?usp=share_link

dghgit commented 5 months ago

Thanks for the report, I think this is now fixed. The current snapshot at https://www.bouncycastle.org/betas includes the patches.

mugz3m commented 5 months ago

We have checked the snapshot with patches and could not reproduce the error. Thanks!