go.crypto/ocsp: allow cert-less responses and support making requests.

Some OCSP responses (notably COMODO's) don't use an intermediate
certificate to sign OCSP responses so this change allowed that.

Additionally, a CreateRequest function is added for creating OCSP
requests.

This change makes one API change: SerialNumber becomes a *big.Int to
match crypto/x509. The original code dates to before encoding/asn1
could cope with big.Ints and using a []byte was a workaround for that.

R=golang-dev
CC=golang-dev
https://golang.org/cl/10402043
diff --git a/ocsp/ocsp.go b/ocsp/ocsp.go
index c022ea2..68e0235 100644
--- a/ocsp/ocsp.go
+++ b/ocsp/ocsp.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -9,16 +9,15 @@
 
 import (
 	"crypto"
-	"crypto/rsa"
 	_ "crypto/sha1"
 	"crypto/x509"
 	"crypto/x509/pkix"
 	"encoding/asn1"
+	"math/big"
 	"time"
 )
 
 var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
-var idSHA1WithRSA = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 1, 5})
 
 // These are internal structures that reflect the ASN.1 structure of an OCSP
 // response. See RFC 2560, section 4.2.
@@ -36,7 +35,7 @@
 	HashAlgorithm pkix.AlgorithmIdentifier
 	NameHash      []byte
 	IssuerKeyHash []byte
-	SerialNumber  asn1.RawValue
+	SerialNumber  *big.Int
 }
 
 type responseASN1 struct {
@@ -79,6 +78,53 @@
 	Reason         int `asn1:"explicit,tag:0,optional"`
 }
 
+var (
+	oidSignatureMD2WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
+	oidSignatureMD5WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
+	oidSignatureSHA1WithRSA     = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
+	oidSignatureSHA256WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
+	oidSignatureSHA384WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
+	oidSignatureSHA512WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
+	oidSignatureDSAWithSHA1     = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
+	oidSignatureDSAWithSHA256   = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
+	oidSignatureECDSAWithSHA1   = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
+	oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
+	oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
+	oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
+)
+
+// TODO(agl): this is taken from crypto/x509 and so should probably be exported
+// from crypto/x509 or crypto/x509/pkix.
+func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
+	switch {
+	case oid.Equal(oidSignatureMD2WithRSA):
+		return x509.MD2WithRSA
+	case oid.Equal(oidSignatureMD5WithRSA):
+		return x509.MD5WithRSA
+	case oid.Equal(oidSignatureSHA1WithRSA):
+		return x509.SHA1WithRSA
+	case oid.Equal(oidSignatureSHA256WithRSA):
+		return x509.SHA256WithRSA
+	case oid.Equal(oidSignatureSHA384WithRSA):
+		return x509.SHA384WithRSA
+	case oid.Equal(oidSignatureSHA512WithRSA):
+		return x509.SHA512WithRSA
+	case oid.Equal(oidSignatureDSAWithSHA1):
+		return x509.DSAWithSHA1
+	case oid.Equal(oidSignatureDSAWithSHA256):
+		return x509.DSAWithSHA256
+	case oid.Equal(oidSignatureECDSAWithSHA1):
+		return x509.ECDSAWithSHA1
+	case oid.Equal(oidSignatureECDSAWithSHA256):
+		return x509.ECDSAWithSHA256
+	case oid.Equal(oidSignatureECDSAWithSHA384):
+		return x509.ECDSAWithSHA384
+	case oid.Equal(oidSignatureECDSAWithSHA512):
+		return x509.ECDSAWithSHA512
+	}
+	return x509.UnknownSignatureAlgorithm
+}
+
 // This is the exposed reflection of the internal OCSP structures.
 
 const (
@@ -96,10 +142,24 @@
 type Response struct {
 	// Status is one of {Good, Revoked, Unknown, ServerFailed}
 	Status                                        int
-	SerialNumber                                  []byte
+	SerialNumber                                  *big.Int
 	ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
 	RevocationReason                              int
 	Certificate                                   *x509.Certificate
+	// TBSResponseData contains the raw bytes of the signed response. If
+	// Certificate is nil then this can be used to verify Signature.
+	TBSResponseData    []byte
+	Signature          []byte
+	SignatureAlgorithm x509.SignatureAlgorithm
+}
+
+// CheckSignatureFrom checks that the signature in resp is a valid signature
+// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
+// the OCSP response contained an intermediate certificate that created the
+// signature. That signature is checked by ParseResponse and only
+// resp.Certificate remains to be validated.
+func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
+	return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
 }
 
 // ParseError results from an invalid OCSP response.
@@ -110,9 +170,9 @@
 }
 
 // ParseResponse parses an OCSP response in DER form. It only supports
-// responses for a single certificate and only those using RSA signatures.
-// Non-RSA responses will result in x509.ErrUnsupportedAlgorithm.
-// Signature errors or parse failures will result in a ParseError.
+// responses for a single certificate. If the response contains a certificate
+// then the signature over the response is checked. Invalid signatures or parse
+// failures will result in a ParseError.
 func ParseResponse(bytes []byte) (*Response, error) {
 	var resp responseASN1
 	rest, err := asn1.Unmarshal(bytes, &resp)
@@ -139,7 +199,7 @@
 		return nil, err
 	}
 
-	if len(basicResp.Certificates) != 1 {
+	if len(basicResp.Certificates) > 1 {
 		return nil, ParseError("OCSP response contains bad number of certificates")
 	}
 
@@ -147,30 +207,24 @@
 		return nil, ParseError("OCSP response contains bad number of responses")
 	}
 
-	ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
-	if err != nil {
-		return nil, err
-	}
+	ret.TBSResponseData = basicResp.TBSResponseData.Raw
+	ret.Signature = basicResp.Signature.RightAlign()
+	ret.SignatureAlgorithm = getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm)
 
-	if ret.Certificate.PublicKeyAlgorithm != x509.RSA || !basicResp.SignatureAlgorithm.Algorithm.Equal(idSHA1WithRSA) {
-		return nil, x509.ErrUnsupportedAlgorithm
-	}
+	if len(basicResp.Certificates) > 0 {
+		ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
+		if err != nil {
+			return nil, err
+		}
 
-	hashType := crypto.SHA1
-	h := hashType.New()
-
-	pub := ret.Certificate.PublicKey.(*rsa.PublicKey)
-	h.Write(basicResp.TBSResponseData.Raw)
-	digest := h.Sum(nil)
-	signature := basicResp.Signature.RightAlign()
-
-	if rsa.VerifyPKCS1v15(pub, hashType, digest, signature) != nil {
-		return nil, ParseError("bad OCSP signature")
+		if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
+			return nil, ParseError("bad OCSP signature")
+		}
 	}
 
 	r := basicResp.TBSResponseData.Responses[0]
 
-	ret.SerialNumber = r.CertID.SerialNumber.Bytes
+	ret.SerialNumber = r.CertID.SerialNumber
 
 	switch {
 	case bool(r.Good):
@@ -189,3 +243,94 @@
 
 	return ret, nil
 }
+
+// https://tools.ietf.org/html/rfc2560#section-4.1.1
+type ocspRequest struct {
+	TBSRequest tbsRequest
+}
+
+type tbsRequest struct {
+	Version     int `asn1:"explicit,tag:0,default:0"`
+	RequestList []request
+}
+
+type request struct {
+	Cert certID
+}
+
+// RequestOptions contains options for constructing OCSP requests.
+type RequestOptions struct {
+	// Hash contains the hash function that should be used when
+	// constructing the OCSP request.
+	Hash crypto.Hash
+}
+
+func (opts *RequestOptions) hash() crypto.Hash {
+	if opts == nil {
+		// SHA-1 is nearly universally used in OCSP.
+		return crypto.SHA1
+	}
+	return opts.Hash
+}
+
+// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If
+// opts is nil then sensible defaults are used.
+func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
+	hashFunc := opts.hash()
+
+	// OCSP seems to be the only place where these raw hash identifiers are
+	// used. I took the following from
+	// http://msdn.microsoft.com/en-us/library/ff635603.aspx
+	var hashOID asn1.ObjectIdentifier
+	switch hashFunc {
+	case crypto.SHA1:
+		hashOID = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
+	case crypto.SHA256:
+		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1})
+	case crypto.SHA384:
+		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2})
+	case crypto.SHA512:
+		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3})
+	default:
+		return nil, x509.ErrUnsupportedAlgorithm
+	}
+
+	if !hashFunc.Available() {
+		return nil, x509.ErrUnsupportedAlgorithm
+	}
+	h := opts.hash().New()
+
+	var publicKeyInfo struct {
+		Algorithm pkix.AlgorithmIdentifier
+		PublicKey asn1.BitString
+	}
+	if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
+		return nil, err
+	}
+
+	h.Write(publicKeyInfo.PublicKey.RightAlign())
+	issuerKeyHash := h.Sum(nil)
+
+	h.Reset()
+	h.Write(issuer.RawSubject)
+	issuerNameHash := h.Sum(nil)
+
+	return asn1.Marshal(ocspRequest{
+		tbsRequest{
+			Version: 0,
+			RequestList: []request{
+				{
+					Cert: certID{
+						pkix.AlgorithmIdentifier{
+							Algorithm:  hashOID,
+							Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
+						},
+						issuerNameHash,
+						issuerKeyHash,
+						cert.SerialNumber,
+					},
+				},
+			},
+		},
+	})
+}
diff --git a/ocsp/ocsp_test.go b/ocsp/ocsp_test.go
index f0e9f94..26c0d23 100644
--- a/ocsp/ocsp_test.go
+++ b/ocsp/ocsp_test.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -6,7 +6,9 @@
 
 import (
 	"bytes"
+	"crypto/x509"
 	"encoding/hex"
+	"math/big"
 	"reflect"
 	"testing"
 	"time"
@@ -21,7 +23,7 @@
 
 	expected := Response{
 		Status:           0,
-		SerialNumber:     []byte{0x1, 0xd0, 0xfa},
+		SerialNumber:     big.NewInt(0x1d0fa),
 		RevocationReason: 0,
 		ThisUpdate:       time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC),
 		NextUpdate:       time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC),
@@ -39,7 +41,7 @@
 		t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status)
 	}
 
-	if !bytes.Equal(resp.SerialNumber, expected.SerialNumber) {
+	if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 {
 		t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber)
 	}
 
@@ -48,6 +50,38 @@
 	}
 }
 
+func TestOCSPDecodeWithoutCert(t *testing.T) {
+	responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex)
+	_, err := ParseResponse(responseBytes)
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func TestOCSPRequest(t *testing.T) {
+	leafCert, _ := hex.DecodeString(leafCertHex)
+	cert, err := x509.ParseCertificate(leafCert)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	issuerCert, _ := hex.DecodeString(issuerCertHex)
+	issuer, err := x509.ParseCertificate(issuerCert)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	request, err := CreateRequest(cert, issuer, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected, _ := hex.DecodeString(ocspRequestHex)
+	if !bytes.Equal(request, expected) {
+		t.Errorf("got %x, wanted %x", request, expected)
+	}
+}
+
 // This OCSP response was taken from Thawte's public OCSP responder.
 // To recreate:
 //   $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443
@@ -105,3 +139,77 @@
 	"f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" +
 	"a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" +
 	"6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42"
+
+const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" +
+	"01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" +
+	"3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" +
+	"456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" +
+	"1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" +
+	"5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" +
+	"82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" +
+	"5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" +
+	"8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" +
+	"6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" +
+	"0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" +
+	"9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" +
+	"20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" +
+	"5a35fca2e054dfa8"
+
+const ocspRequestHex = "30563054a003020100304d304b3049300906052b0e03021a05000414c0fe0278fc991888" +
+	"91b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210" +
+	"017f77deb3bcbb235d44ccc7dba62e72"
+
+const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" +
+	"864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" +
+	"7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" +
+	"333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" +
+	"766572204341202d20436c617373203331493047060355040b13407777772e7665726973" +
+	"69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" +
+	"204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" +
+	"170d3133313233313233353935395a3068310b3009060355040613025553311330110603" +
+	"550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" +
+	"173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" +
+	"2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" +
+	"818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" +
+	"23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" +
+	"5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" +
+	"c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" +
+	"82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" +
+	"01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" +
+	"7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" +
+	"2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" +
+	"726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" +
+	"03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" +
+	"30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" +
+	"20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" +
+	"092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" +
+	"81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" +
+	"67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" +
+	"9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817"
+
+const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" +
+	"864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" +
+	"566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" +
+	"6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" +
+	"1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" +
+	"301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" +
+	"0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" +
+	"69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" +
+	"3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" +
+	"6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" +
+	"5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" +
+	"e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" +
+	"bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" +
+	"3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" +
+	"f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" +
+	"0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" +
+	"2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" +
+	"636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" +
+	"030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" +
+	"0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" +
+	"a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" +
+	"300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" +
+	"adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" +
+	"f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" +
+	"e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" +
+	"d68071"