I'm writing certificate revocation validation using OCSP request to get actual status. I send request, but getting error. ERROR: ocsp: error from server: malformed. I found error return in source: MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01}
, but don't understand what causes error??
func CheckRevocation(cert *x509.Certificate) error {
var (
buffer []byte
output []byte
OCSPResponse *ocsp.Response
OCSPURL string
IssuerURL string
httpRequest *http.Request
httpResponse *http.Response
)
if len(cert.OCSPServer) > 0 {
OCSPURL = cert.OCSPServer[0]
}
if len(cert.IssuingCertificateURL) > 0 {
IssuerURL = cert.IssuingCertificateURL[0]
}
issuer, err := DownloadCert(IssuerURL) // return *x509.Certificate, err
if err != nil {
return err
}
opts := &ocsp.RequestOptions{
Hash: crypto.SHA256,
}
buffer, err = ocsp.CreateRequest(cert, issuer, opts)
if err != nil {
return err
}
httpRequest, err = http.NewRequest("GET", OCSPURL, nil)
if err != nil {
return err
}
httpRequest.Header.Add("Content-Type", "application/ocsp-request")
httpRequest.Header.Add("Accept", "application/ocsp-response")
writer := bytes.NewBuffer(buffer)
httpRequest.Write(writer)
httpClient := &http.Client{}
httpResponse, err = httpClient.Do(httpRequest)
if err != nil {
return err
}
defer httpResponse.Body.Close()
output, err = ioutil.ReadAll(httpResponse.Body)
if err != nil {
return err
}
OCSPResponse, err = ocsp.ParseResponse(output, issuer)
if err != nil {
return err
}
debugPrint("OCSP", "result: %d", OCSPResponse.Status)
return nil
}
EXAMPLE OF CERTIFICATE:
...
<ds:X509Certificate>
MIIG9DCCBNygAwIBAgIUTFVCYjrFFRdWjgJW0G8fUs6LLk4wDQYJKoZIhvcNAQELBQAwgc4xCzAJ
BgNVBAYTAktaMRUwEwYDVQQHDAzQkNCh0KLQkNCd0JAxFTATBgNVBAgMDNCQ0KHQotCQ0J3QkDFM
MEoGA1UECgxD0KDQnNCaIMKr0JzQldCc0JvQldCa0JXQotCi0IbQmiDQotCV0KXQndCY0JrQkNCb
0KvSmiDSmtCr0JfQnNCV0KLCuzFDMEEGA1UEAww60rDQm9Ci0KLQq9KaINCa0KPTmNCb0JDQndCU
0KvQoNCj0KjQqyDQntCg0KLQkNCb0KvSmiAoUlNBKTAeFw0xNzA3MjcwMzU1MDZaFw0xODA3Mjcw
MzU1MDZaMIHJMSwwKgYDVQQDDCPQkdCQ0JnQotCj0KDQodCr0J3QntCSINCU0JDQndCY0K/QoDEf
MB0GA1UEBAwW0JHQkNCZ0KLQo9Cg0KHQq9Cd0J7QkjEYMBYGA1UEBRMPSUlOOTIwNzI3MzAwMDQ0
MQswCQYDVQQGEwJLWjEVMBMGA1UEBwwM0JDQm9Cc0JDQotCrMRUwEwYDVQQIDAzQkNCb0JzQkNCi
0KsxIzAhBgNVBCoMGtCh0JXQmdCi0JrQkNCh0KvQnNCe0JLQmNCnMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAvW0Lyoex/kkhq5Xb5uCOtEpp4zjc34M5UGftcgmY6FXvlCaPm4415cmk
Kyaz6M+vmsK3T/wH3S2Up5cLKo022BgpBTYg6+lPUQgigYM7PPc20aLySrMg+Gu4HitokrdWgA/H
hjr14HAOFNiEZm7UpeLAhBfuAz/S9TeCct0C/dp75X8K7zOdXX1n/npnMZKMStPVJ94Cbdpprz/O
lNWzk+MGUB5+2yy4k4zBUamyEk8QzsJZID4Hva8ZIwqSXe4gyCe46iPxPZ8EKiwR4Pn6BXj0k7G1
a8A1jYEqc91QMX+L4CCS5M+BeUvbrcdMjNEoy71YG6m9qgNsBGl7WueMawIDAQABo4IByzCCAccw
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggqgw4DAwQBATAPBgNVHSMECDAG
gARVtbTiMB0GA1UdDgQWBBQKnKaePX9Y74pplb7yI5ql8zxiJDBeBgNVHSAEVzBVMFMGByqDDgMD
AgQwSDAhBggrBgEFBQcCARYVaHR0cDovL3BraS5nb3Yua3ovY3BzMCMGCCsGAQUFBwICMBcMFWh0
dHA6Ly9wa2kuZ292Lmt6L2NwczBOBgNVHR8ERzBFMEOgQaA/hh1odHRwOi8vY3JsLnBraS5nb3Yu
a3ovcnNhLmNybIYeaHR0cDovL2NybDEucGtpLmdvdi5rei9yc2EuY3JsMFIGA1UdLgRLMEkwR6BF
oEOGH2h0dHA6Ly9jcmwucGtpLmdvdi5rei9kX3JzYS5jcmyGIGh0dHA6Ly9jcmwxLnBraS5nb3Yu
a3ovZF9yc2EuY3JsMGIGCCsGAQUFBwEBBFYwVDAuBggrBgEFBQcwAoYiaHR0cDovL3BraS5nb3Yu
a3ovY2VydC9wa2lfcnNhLmNlcjAiBggrBgEFBQcwAYYWaHR0cDovL29jc3AucGtpLmdvdi5rejAN
BgkqhkiG9w0BAQsFAAOCAgEAColZth/p4wVdcPU1AHTMhNeyLtSJI4K5A7/NoOsqYsH5qpE89gPI
mxB4NAvtmHD49f/lHLvzeIBh+snO+lfJZYXaWcYwU1+dJRyB/bE+W6vcEa5N79eihSyl9fsQTYcz
jBsXzUx0Sv2vAiZH+RIowSsg/m9+UZDt5eNcL7eqkr/JDs0I5VVYXFKwNP1rPam4jfuJKB9w/bEg
6G6RM0/DGaXxLAimVB6gLQzT1hdQzgG8YOERJxjlTeRUICUiEqFz5mZzlJ6zb2+N7lUCzRu385o1
DeWjRJZaTxFKM9JJv8a6zPjcuFA+PIsDy9GSLby1OfZaJJo/7w4iLtJiYDuyMTXisnOknmVr5LC6
fft4AXOq7zOTn7t5r3T9lb5VmorfnqdqSXrep6c/dlkSlyP2mYhUE3JOSQTraJQH/jjcWH5hfewb
/9kPWqDlTpBnok9pcciRSYOgzqkpe0CJ3ZNyj+YNuL58O+TkV9MOwe8wWrWe8rVYV61E597WJZJ/
m6qKBPYUy+zoRVK/XdYYAMsBC2zHrz8n7Z8k6s9FQo4YLgprMQh6Hcq42PgnCZZGxxJ4wU44STUj
HCtohHNYjhz+sZfKg6KEFPzGJN1O7rYd8q0Gl9vQtKMjIsETZ7BRYbXxuzMVA2CMhxiXJS929qH2
ce48JWaAdMkyzyjcF8t3tVY=
</ds:X509Certificate>
This certificate is valid, but cannot call OCSP to check it's status. May be my call is incorrect. Does anyone have ideas?
The standard allows for requests to made via GET or POST. See the code below for an example that works with the POST method. This example works in my company's corporate PKI and almost works with the NIST PIV test cards (https://csrc.nist.gov/projects/piv/nist-personal-identity-verification-test-cards), but trips over a bug in Go that may have been resolved in 1.11 (see https://github.com/golang/go/issues/21527)
Note that some OCSP responders require the host header. Also, both of the OSCP responders in my environment want SHA1 for the hash algorithm and fail when SHA256 is used.
func isCertificateRevokedByOCSP(commonName string, clientCert, issuerCert *x509.Certificate, ocspServer string) bool {
opts := &ocsp.RequestOptions{Hash: crypto.SHA1}
buffer, err := ocsp.CreateRequest(clientCert, issuerCert, opts)
if err != nil {
return false
}
httpRequest, err := http.NewRequest(http.MethodPost, ocspServer, bytes.NewBuffer(buffer))
if err != nil {
return false
}
ocspUrl, err := url.Parse(ocspServer)
if err != nil {
return false
}
httpRequest.Header.Add("Content-Type", "application/ocsp-request")
httpRequest.Header.Add("Accept", "application/ocsp-response")
httpRequest.Header.Add("host", ocspUrl.Host)
httpClient := &http.Client{}
httpResponse, err := httpClient.Do(httpRequest)
if err != nil {
return false
}
defer httpResponse.Body.Close()
output, err := ioutil.ReadAll(httpResponse.Body)
if err != nil {
return false
}
ocspResponse, err := ocsp.ParseResponse(output, issuerCert)
if err != nil {
return false
}
if ocspResponse.Status == ocsp.Revoked {
logger.GetLogger().Warnf("certificate '%s' has been revoked by OCSP server %s, refusing connection", commonName, ocspServer)
return true
} else {
return false
}
}