How to fix "CCertRequest::Submit: The RPC server is unavailable. 0x800706ba" error?

0

Scenario:
I am learning AWS CloudHSM. So far, I have

  • created an EC2 instance with Windows Server 2019 Datacenter as OS
  • created a certification authority (root CA) on this server with Dintinguised Name "CN=myservername-CA1" (https://docs.aws.amazon.com/cloudhsm/latest/userguide/win-ca-setup.html )
  • while connected to EC2 instance via RDP, I can login to my cloud hsm account and can manage users, create new keys etc.

Details of CA:

  • Provider: RSA#Cavium Key Storage Provider
  • Key Length: 2048
  • Hash Algorithm: SHA256
  • Distinguished Name: CN=myservername-CA1
  • Cert Database log: C:\Windows\system32\CertLog

Now, I have developed a sample .Net WebAPI application which should send a CSR request to my CA and CA should return the signed certificate to the requester. This application is hosted as a web app on IIS on the same EC2 instance.

Source Code (https://blogs.msdn.microsoft.com/alejacma/2008/09/05/how-to-create-a-certificate-request-with-certenroll-and-net-c/ ):

using CloudHsmDemo.Models;
using System;
using System.Threading.Tasks;
using CERTENROLLLib;
using CERTCLILib;

namespace CloudHsmDemo.Services
{
    public interface ICertificateService
    {
        Task<CertificateSigningResponse> SignAsync(CertificateSigningRequest csr);
    }

    public class CertificateService : ICertificateService
    {
        private const int CC_DEFAULTCONFIG = 0;

        private const int CC_UIPICKCONFIG = 0x1;

        private const int CR_IN_BASE64 = 0x1;

        private const int CR_IN_FORMATANY = 0;

        private const int CR_IN_PKCS10 = 0x100;

        private const int CR_DISP_ISSUED = 0x3;

        private const int CR_DISP_UNDER_SUBMISSION = 0x5;

        private const int CR_OUT_BASE64 = 0x1;

        private const int CR_OUT_CHAIN = 0x100;

        public async Task<CertificateSigningResponse> SignAsync(CertificateSigningRequest csr)
        {
            if (csr.ShouldReturnDummyData)
            {
                return await DummySigningAsync(csr);
            }
            else
            {
                return await ActualSigningAsync(csr);
            }
        }

        private async Task<CertificateSigningResponse> DummySigningAsync(CertificateSigningRequest csr)
        {
            return PopulateCertificateSigningResponse("Sample Certificate", "Sample Message");
        }

        private async Task<CertificateSigningResponse> ActualSigningAsync(CertificateSigningRequest csr)
        {
            //  Create all the objects that will be required

            CCertConfig objCertConfig = new CCertConfigClass();

            CCertRequest objCertRequest = new CCertRequestClass();

            // string strCAConfig;

            string strRequest;

            int iDisposition;

            string strDisposition;

            string strCert;

            CertificateSigningResponse certificateSigningResponse;

            try

            {

                strRequest = await CreateCertificateSigningRequest(csr);


                // Get CA config from UI

                // strCAConfig = objCertConfig.GetConfig(CC_DEFAULTCONFIG);

                //strCAConfig = objCertConfig.GetConfig(CC_UIPICKCONFIG);


                // Submit the request

                iDisposition = objCertRequest.Submit(

                    CR_IN_BASE64 | CR_IN_FORMATANY,

                    strRequest,

                    null,

                    "<my_ec2_instance_public_dns>\\<my_server_name>"

                );

                // Check the submission status

                if (CR_DISP_ISSUED != iDisposition) // Not enrolled

                {

                    strDisposition = objCertRequest.GetDispositionMessage();


                    if (CR_DISP_UNDER_SUBMISSION == iDisposition) // Pending
                    {
                        certificateSigningResponse = PopulateCertificateSigningResponse(string.Empty, $"The submission is pending: {strDisposition}");
                    }

                    else // Failed

                    {
                        certificateSigningResponse = PopulateCertificateSigningResponse(string.Empty, $"The submission failed: {strDisposition}; Last Status: {objCertRequest.GetLastStatus().ToString()}");
                    }

                }


                // Get the certificate

                strCert = objCertRequest.GetCertificate(

                    CR_OUT_BASE64 | CR_OUT_CHAIN

                );


                certificateSigningResponse = PopulateCertificateSigningResponse(strCert, "Certificate signing process succeeded.");

            }

            catch (Exception ex)

            {

                certificateSigningResponse = PopulateCertificateSigningResponse(string.Empty, ex.Message);

            }
            if (certificateSigningResponse == null)
            {
                certificateSigningResponse = PopulateCertificateSigningResponse(string.Empty, "Certificate signing process failed.");
            }
            return certificateSigningResponse;
        }

        // this method creates a request string properly when 
        private async Task<string> CreateCertificateSigningRequest(CertificateSigningRequest csr)
        {
            //  Create all the objects that will be required

            CX509CertificateRequestPkcs10 objPkcs10 = new CX509CertificateRequestPkcs10Class();

            CX509PrivateKey objPrivateKey = new CX509PrivateKeyClass();

            CCspInformation objCSP = new CCspInformationClass();

            CCspInformations objCSPs = new CCspInformationsClass();

            CX500DistinguishedName objDN = new CX500DistinguishedNameClass();

            CX509Enrollment objEnroll = new CX509EnrollmentClass();

            CObjectIds objObjectIds = new CObjectIdsClass();

            CObjectId objObjectId = new CObjectIdClass();

            CX509ExtensionKeyUsage objExtensionKeyUsage = new CX509ExtensionKeyUsageClass();

            CX509ExtensionEnhancedKeyUsage objX509ExtensionEnhancedKeyUsage = new CX509ExtensionEnhancedKeyUsageClass();

            string strRequest;


            try

            {
                //  Initialize the csp object using the desired Cryptograhic Service Provider (CSP)

                objCSP.InitializeFromName("Microsoft Enhanced Cryptographic Provider v1.0");


                //objCSP.InitializeFromName("Cavium Key Storage Provider");

                //  Add this CSP object to the CSP collection object

                objCSPs.Add(objCSP);


                //  Provide key container name, key length and key spec to the private key object

                objPrivateKey.Length = csr.KeySize;

                objPrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE;

                objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES;

                objPrivateKey.MachineContext = false;


                //  Provide the CSP collection object (in this case containing only 1 CSP object)

                //  to the private key object

                objPrivateKey.CspInformations = objCSPs;


                //  Create the actual key pair
                objPrivateKey.Create();


                //  Initialize the PKCS#10 certificate request object based on the private key.

                //  Using the context, indicate that this is a user certificate request and don't

                //  provide a template name

                objPkcs10.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, objPrivateKey, "");


                // Key Usage Extension

                objExtensionKeyUsage.InitializeEncode(

                    X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE |

                    X509KeyUsageFlags.XCN_CERT_NON_REPUDIATION_KEY_USAGE |

                    X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE |

                    X509KeyUsageFlags.XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE

                );

                objPkcs10.X509Extensions.Add((CX509Extension)objExtensionKeyUsage);


                // Enhanced Key Usage Extension

                objObjectId.InitializeFromValue("1.3.6.1.5.5.7.3.2"); // OID for Client Authentication usage

                objObjectIds.Add(objObjectId);

                objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);

                objPkcs10.X509Extensions.Add((CX509Extension)objX509ExtensionEnhancedKeyUsage);


                //  Encode the name in using the Distinguished Name object

                objDN.Encode("CN=<myservername>-CA1", X500NameFlags.XCN_CERT_NAME_STR_NONE);


                //  Assing the subject name by using the Distinguished Name object initialized above

                objPkcs10.Subject = objDN;


                // Create enrollment request

                objEnroll.InitializeFromRequest(objPkcs10);

                strRequest = objEnroll.CreateRequest(

                    EncodingType.XCN_CRYPT_STRING_BASE64

                );
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return strRequest;
        }

        private CertificateSigningResponse PopulateCertificateSigningResponse(string certificate, string message)
        {
            var responseObject = new CertificateSigningResponse
            {
                Certificate = certificate,
                Message = message,
                DateTimeInUTC = DateTime.UtcNow,
                Status = string.IsNullOrWhiteSpace(certificate) == true ? "Fail" : "Success"
            };
            return responseObject;
        }
    }
}

My sample JSON request:

{
    "CommonName":"My Test CSR",
    "Organization":"My Office",
    "OrganizationalUnit":"My Department",
    "CityOrLocality":"Sydney",
    "StateOrProvince":"NSW",
    "CountryOrRegion":"AU",
    "KeySize":2048,
    "ShouldReturnDummyData": false
}

Problem(s):

  • when "Cavium Key Storage Provider" or "RSA#Cavium Key Storage Provider" is used to initialize objCSP, "Invalid provider specified. (Exception from HRESULT: 0x80090013)" exception is thrown

  • when "Microsoft Enhanced Cryptographic Provider v1.0" is used to initialize objCSP, "CCertRequest::Submit: The RPC server is unavailable. 0x800706ba" exception is thrown

To resolve the "The RPC server is unavailable" issue, I have followed the steps https://itworldjd.wordpress.com/2015/10/21/pki-certificates-troubleshooting-certificate-enrollment-rpc-server-is-unavailable/ but no luck.

c#
amazon-web-services
amazon-ec2
cryptography
hsm
asked on Stack Overflow Feb 4, 2019 by vpv • edited Feb 4, 2019 by vpv

1 Answer

0

I hit this error too. Hopefully someone can benefit from how I addressed it.

After requesting a new cert over web enrollment I also got the error.

CCertRequest::Submit: The RPC server is unavailable. 0x800706ba (WIN32: 1722 RPC_S_SERVER_UNAVAILABLE)

Without going into all the detail of DCOM permissions you need to ensure you are accessing the Certificate web server remotely and not locally from the CA server.

answered on Stack Overflow Oct 13, 2020 by Michael

User contributions licensed under CC BY-SA 3.0