Home > database >  EST with Bouncy Castle
EST with Bouncy Castle

Time:04-02

I try to request a new certificate via EST protocol from the EST test service URL “https://testrfc7030.com/”. The program uses Bouncy Castle for this.

I have already configured the EST service’s TA and my client certificate obtained from them. I also use the BC JSSE provider to get access to the “tls-unique” channel binding value.

        eSTService = new JsseESTServiceBuilder(Config.CredAdmin.caHost, trustManagers)
                    .withKeyManagers(keyManagers)
                    .withProvider(BouncyCastleJsseProvider.PROVIDER_NAME)
                    .withChannelBindingProvider(new ChannelBindingProvider() {
                        //Use an anonymous binding provider that supports linking 
                        //Identity and POP Information (RFC7030, Section 3.5.), that
                        //relies on Channel Bindings for TLS (RFC5929) using "tls-unique".
                        public boolean canAccessChannelBinding(Socket sock) {
                            boolean ret = sock instanceof BCSSLSocket;
                            if (!ret)
                                //should never happen
                                MyUtils.LambdaLogger.error("Can't get channel binding value, check if BouncyCastleJsseProvider could be loaded.");
                            return ret;
                        }
                        public byte[] getChannelBinding(Socket sock, String binding) {
                            BCSSLConnection bcon = ((BCSSLSocket)sock).getConnection();
                            if (bcon == null) {
                                //should never happen
                                MyUtils.LambdaLogger.error("Can't get \"%s\" channel binding value, check if BouncyCastleJsseProvider could be loaded.", binding);
                                return null;
                            }
                            byte[] ret = bcon.getChannelBinding(binding);
                            MyUtils.LambdaLogger.debug("retrieved %d bytes \"%s\" channel binding value", ret.length, binding);
                            return ret;
                        }
                    })
                    .build();

and

Security.addProvider(new BouncyCastleJsseProvider());

When I configure EST service port 9443 – that requires my client cert but no TLS channel binding – I do get a new certificate:

enter image description here

However, when I configure port 443 – that also needs TLS channel binding – although I get 12 bytes of “tls-unique” from BC JSSE, these won’t get accepted by the EST service testrfc7030.com, so it gives me an HTTP 401 – Unauthorized:

enter image description here

My problem is, I don’t know, what’s wrong:

  • my code
  • the BC JSSE implementation of “tls-unique” (RFC 5929)
  • the EST service’s implementation of “tls-unique” (RFC 5929)?

Does someone have an implementation that works with the EST service “testrfc7030.com:443” art has at least an idea, what's wrong?

---Update 1--- I'm creating the ContentSigner as following:

ContentSigner signer = 
        new JcaContentSignerBuilder(MyUtils.Crypto.sha256WithRSAEncryption)
        .setProvider(BouncyCastleProvider.PROVIDER_NAME)
        .build(keyPair.getPrivate());

and the csrBuilder:

    PKCS10CertificationRequestBuilder csrBuilder =
        new PKCS10CertificationRequestBuilder(
            new X500Name(subjectDN),
            SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()));
    csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extGen.generate());

with

    ExtensionsGenerator extGen = new ExtensionsGenerator();
    ...

This we then use as following:

    EnrollmentResponse resp = eSTService.simpleEnrollPoP(false, cb.csrBuilder, cb.signer, null);

CodePudding user response:

Based on the input by Peter we were able to fix this problem as following:

    //just for testrfc7030.com
    ESTAuth auth = new JcaHttpAuthBuilder(null, "estuser", "estpwd".toCharArray())
            .setNonceGenerator(new SecureRandom())
            .setProvider("BC")
            .build();
    
    EnrollmentResponse resp = eSTService.simpleEnrollPoP(false, cb.csrBuilder, cb.signer, auth);

It turned out, that testrfc3070 requires the following authentication schemes:

  • Port 443: requires HTTP user auth identity POP linking
  • Port 8443: requires HTTP user auth but no identity POP linking
  • Port 9443: requires user auth with client certificate (obtained via Port 8443 or Port 443) but no identity POP linking

identity POP linking = TLS channel binding

  • Related