OSDN Git Service

Add Go frontend, libgo library, and Go testsuite.
[pf3gnuchains/gcc-fork.git] / libgo / go / crypto / ocsp / ocsp.go
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // This package parses OCSP responses as specified in RFC 2560. OCSP responses
6 // are signed messages attesting to the validity of a certificate for a small
7 // period of time. This is used to manage revocation for X.509 certificates.
8 package ocsp
9
10 import (
11         "asn1"
12         "crypto/rsa"
13         "crypto/sha1"
14         "crypto/x509"
15         "os"
16         "time"
17 )
18
19 var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
20 var idSHA1WithRSA = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 1, 5})
21
22 // These are internal structures that reflect the ASN.1 structure of an OCSP
23 // response. See RFC 2560, section 4.2.
24
25 const (
26         ocspSuccess       = 0
27         ocspMalformed     = 1
28         ocspInternalError = 2
29         ocspTryLater      = 3
30         ocspSigRequired   = 4
31         ocspUnauthorized  = 5
32 )
33
34 type rdnSequence []relativeDistinguishedNameSET
35
36 type relativeDistinguishedNameSET []attributeTypeAndValue
37
38 type attributeTypeAndValue struct {
39         Type  asn1.ObjectIdentifier
40         Value interface{}
41 }
42
43 type algorithmIdentifier struct {
44         Algorithm asn1.ObjectIdentifier
45 }
46
47 type certID struct {
48         HashAlgorithm algorithmIdentifier
49         NameHash      []byte
50         IssuerKeyHash []byte
51         SerialNumber  asn1.RawValue
52 }
53
54 type responseASN1 struct {
55         Status   asn1.Enumerated
56         Response responseBytes "explicit,tag:0"
57 }
58
59 type responseBytes struct {
60         ResponseType asn1.ObjectIdentifier
61         Response     []byte
62 }
63
64 type basicResponse struct {
65         TBSResponseData    responseData
66         SignatureAlgorithm algorithmIdentifier
67         Signature          asn1.BitString
68         Certificates       []asn1.RawValue "explicit,tag:0,optional"
69 }
70
71 type responseData struct {
72         Raw           asn1.RawContent
73         Version       int         "optional,default:1,explicit,tag:0"
74         RequestorName rdnSequence "optional,explicit,tag:1"
75         KeyHash       []byte      "optional,explicit,tag:2"
76         ProducedAt    *time.Time
77         Responses     []singleResponse
78 }
79
80 type singleResponse struct {
81         CertID     certID
82         Good       asn1.Flag   "explicit,tag:0,optional"
83         Revoked    revokedInfo "explicit,tag:1,optional"
84         Unknown    asn1.Flag   "explicit,tag:2,optional"
85         ThisUpdate *time.Time
86         NextUpdate *time.Time "explicit,tag:0,optional"
87 }
88
89 type revokedInfo struct {
90         RevocationTime *time.Time
91         Reason         int "explicit,tag:0,optional"
92 }
93
94 // This is the exposed reflection of the internal OCSP structures.
95
96 const (
97         // Good means that the certificate is valid.
98         Good = iota
99         // Revoked means that the certificate has been deliberately revoked.
100         Revoked = iota
101         // Unknown means that the OCSP responder doesn't know about the certificate.
102         Unknown = iota
103         // ServerFailed means that the OCSP responder failed to process the request.
104         ServerFailed = iota
105 )
106
107 // Response represents an OCSP response. See RFC 2560.
108 type Response struct {
109         // Status is one of {Good, Revoked, Unknown, ServerFailed}
110         Status                                        int
111         SerialNumber                                  []byte
112         ProducedAt, ThisUpdate, NextUpdate, RevokedAt *time.Time
113         RevocationReason                              int
114         Certificate                                   *x509.Certificate
115 }
116
117 // ParseError results from an invalid OCSP response.
118 type ParseError string
119
120 func (p ParseError) String() string {
121         return string(p)
122 }
123
124 // ParseResponse parses an OCSP response in DER form. It only supports
125 // responses for a single certificate and only those using RSA signatures.
126 // Non-RSA responses will result in an x509.UnsupportedAlgorithmError.
127 // Signature errors or parse failures will result in a ParseError.
128 func ParseResponse(bytes []byte) (*Response, os.Error) {
129         var resp responseASN1
130         rest, err := asn1.Unmarshal(bytes, &resp)
131         if err != nil {
132                 return nil, err
133         }
134         if len(rest) > 0 {
135                 return nil, ParseError("trailing data in OCSP response")
136         }
137
138         ret := new(Response)
139         if resp.Status != ocspSuccess {
140                 ret.Status = ServerFailed
141                 return ret, nil
142         }
143
144         if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
145                 return nil, ParseError("bad OCSP response type")
146         }
147
148         var basicResp basicResponse
149         rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
150         if err != nil {
151                 return nil, err
152         }
153
154         if len(basicResp.Certificates) != 1 {
155                 return nil, ParseError("OCSP response contains bad number of certificates")
156         }
157
158         if len(basicResp.TBSResponseData.Responses) != 1 {
159                 return nil, ParseError("OCSP response contains bad number of responses")
160         }
161
162         ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
163         if err != nil {
164                 return nil, err
165         }
166
167         if ret.Certificate.PublicKeyAlgorithm != x509.RSA || !basicResp.SignatureAlgorithm.Algorithm.Equal(idSHA1WithRSA) {
168                 return nil, x509.UnsupportedAlgorithmError{}
169         }
170
171         h := sha1.New()
172         hashType := rsa.HashSHA1
173
174         pub := ret.Certificate.PublicKey.(*rsa.PublicKey)
175         h.Write(basicResp.TBSResponseData.Raw)
176         digest := h.Sum()
177         signature := basicResp.Signature.RightAlign()
178
179         if rsa.VerifyPKCS1v15(pub, hashType, digest, signature) != nil {
180                 return nil, ParseError("bad OCSP signature")
181         }
182
183         r := basicResp.TBSResponseData.Responses[0]
184
185         ret.SerialNumber = r.CertID.SerialNumber.Bytes
186
187         switch {
188         case bool(r.Good):
189                 ret.Status = Good
190         case bool(r.Unknown):
191                 ret.Status = Unknown
192         default:
193                 ret.Status = Revoked
194                 ret.RevokedAt = r.Revoked.RevocationTime
195                 ret.RevocationReason = r.Revoked.Reason
196         }
197
198         ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
199         ret.ThisUpdate = r.ThisUpdate
200         ret.NextUpdate = r.NextUpdate
201
202         return ret, nil
203 }