revoked.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. // Copyright 2017 Google Inc. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. package x509
  6. import (
  7. "bytes"
  8. "encoding/pem"
  9. "time"
  10. "github.com/google/certificate-transparency-go/asn1"
  11. "github.com/google/certificate-transparency-go/x509/pkix"
  12. )
  13. // OID values for CRL extensions (TBSCertList.Extensions), RFC 5280 s5.2.
  14. var (
  15. OIDExtensionCRLNumber = asn1.ObjectIdentifier{2, 5, 29, 20}
  16. OIDExtensionDeltaCRLIndicator = asn1.ObjectIdentifier{2, 5, 29, 27}
  17. OIDExtensionIssuingDistributionPoint = asn1.ObjectIdentifier{2, 5, 29, 28}
  18. )
  19. // OID values for CRL entry extensions (RevokedCertificate.Extensions), RFC 5280 s5.3
  20. var (
  21. OIDExtensionCRLReasons = asn1.ObjectIdentifier{2, 5, 29, 21}
  22. OIDExtensionInvalidityDate = asn1.ObjectIdentifier{2, 5, 29, 24}
  23. OIDExtensionCertificateIssuer = asn1.ObjectIdentifier{2, 5, 29, 29}
  24. )
  25. // RevocationReasonCode represents the reason for a certificate revocation; see RFC 5280 s5.3.1.
  26. type RevocationReasonCode asn1.Enumerated
  27. // RevocationReasonCode values.
  28. var (
  29. Unspecified = RevocationReasonCode(0)
  30. KeyCompromise = RevocationReasonCode(1)
  31. CACompromise = RevocationReasonCode(2)
  32. AffiliationChanged = RevocationReasonCode(3)
  33. Superseded = RevocationReasonCode(4)
  34. CessationOfOperation = RevocationReasonCode(5)
  35. CertificateHold = RevocationReasonCode(6)
  36. RemoveFromCRL = RevocationReasonCode(8)
  37. PrivilegeWithdrawn = RevocationReasonCode(9)
  38. AACompromise = RevocationReasonCode(10)
  39. )
  40. // ReasonFlag holds a bitmask of applicable revocation reasons, from RFC 5280 s4.2.1.13
  41. type ReasonFlag int
  42. // ReasonFlag values.
  43. const (
  44. UnusedFlag ReasonFlag = 1 << iota
  45. KeyCompromiseFlag
  46. CACompromiseFlag
  47. AffiliationChangedFlag
  48. SupersededFlag
  49. CessationOfOperationFlag
  50. CertificateHoldFlag
  51. PrivilegeWithdrawnFlag
  52. AACompromiseFlag
  53. )
  54. // CertificateList represents the ASN.1 structure of the same name from RFC 5280, s5.1.
  55. // It has the same content as pkix.CertificateList, but the contents include parsed versions
  56. // of any extensions.
  57. type CertificateList struct {
  58. Raw asn1.RawContent
  59. TBSCertList TBSCertList
  60. SignatureAlgorithm pkix.AlgorithmIdentifier
  61. SignatureValue asn1.BitString
  62. }
  63. // ExpiredAt reports whether now is past the expiry time of certList.
  64. func (certList *CertificateList) ExpiredAt(now time.Time) bool {
  65. return now.After(certList.TBSCertList.NextUpdate)
  66. }
  67. // Indication of whether extensions need to be critical or non-critical. Extensions that
  68. // can be either are omitted from the map.
  69. var listExtCritical = map[string]bool{
  70. // From RFC 5280...
  71. OIDExtensionAuthorityKeyId.String(): false, // s5.2.1
  72. OIDExtensionIssuerAltName.String(): false, // s5.2.2
  73. OIDExtensionCRLNumber.String(): false, // s5.2.3
  74. OIDExtensionDeltaCRLIndicator.String(): true, // s5.2.4
  75. OIDExtensionIssuingDistributionPoint.String(): true, // s5.2.5
  76. OIDExtensionFreshestCRL.String(): false, // s5.2.6
  77. OIDExtensionAuthorityInfoAccess.String(): false, // s5.2.7
  78. }
  79. var certExtCritical = map[string]bool{
  80. // From RFC 5280...
  81. OIDExtensionCRLReasons.String(): false, // s5.3.1
  82. OIDExtensionInvalidityDate.String(): false, // s5.3.2
  83. OIDExtensionCertificateIssuer.String(): true, // s5.3.3
  84. }
  85. // IssuingDistributionPoint represents the ASN.1 structure of the same
  86. // name
  87. type IssuingDistributionPoint struct {
  88. DistributionPoint distributionPointName `asn1:"optional,tag:0"`
  89. OnlyContainsUserCerts bool `asn1:"optional,tag:1"`
  90. OnlyContainsCACerts bool `asn1:"optional,tag:2"`
  91. OnlySomeReasons asn1.BitString `asn1:"optional,tag:3"`
  92. IndirectCRL bool `asn1:"optional,tag:4"`
  93. OnlyContainsAttributeCerts bool `asn1:"optional,tag:5"`
  94. }
  95. // TBSCertList represents the ASN.1 structure of the same name from RFC
  96. // 5280, section 5.1. It has the same content as pkix.TBSCertificateList
  97. // but the extensions are included in a parsed format.
  98. type TBSCertList struct {
  99. Raw asn1.RawContent
  100. Version int
  101. Signature pkix.AlgorithmIdentifier
  102. Issuer pkix.RDNSequence
  103. ThisUpdate time.Time
  104. NextUpdate time.Time
  105. RevokedCertificates []*RevokedCertificate
  106. Extensions []pkix.Extension
  107. // Cracked out extensions:
  108. AuthorityKeyID []byte
  109. IssuerAltNames GeneralNames
  110. CRLNumber int
  111. BaseCRLNumber int // -1 if no delta CRL present
  112. IssuingDistributionPoint IssuingDistributionPoint
  113. IssuingDPFullNames GeneralNames
  114. FreshestCRLDistributionPoint []string
  115. OCSPServer []string
  116. IssuingCertificateURL []string
  117. }
  118. // ParseCertificateList parses a CertificateList (e.g. a CRL) from the given
  119. // bytes. It's often the case that PEM encoded CRLs will appear where they
  120. // should be DER encoded, so this function will transparently handle PEM
  121. // encoding as long as there isn't any leading garbage.
  122. func ParseCertificateList(clBytes []byte) (*CertificateList, error) {
  123. if bytes.HasPrefix(clBytes, pemCRLPrefix) {
  124. block, _ := pem.Decode(clBytes)
  125. if block != nil && block.Type == pemType {
  126. clBytes = block.Bytes
  127. }
  128. }
  129. return ParseCertificateListDER(clBytes)
  130. }
  131. // ParseCertificateListDER parses a DER encoded CertificateList from the given bytes.
  132. // For non-fatal errors, this function returns both an error and a CertificateList
  133. // object.
  134. func ParseCertificateListDER(derBytes []byte) (*CertificateList, error) {
  135. var errs Errors
  136. // First parse the DER into the pkix structures.
  137. pkixList := new(pkix.CertificateList)
  138. if rest, err := asn1.Unmarshal(derBytes, pkixList); err != nil {
  139. errs.AddID(ErrInvalidCertList, err)
  140. return nil, &errs
  141. } else if len(rest) != 0 {
  142. errs.AddID(ErrTrailingCertList)
  143. return nil, &errs
  144. }
  145. // Transcribe the revoked certs but crack out extensions.
  146. revokedCerts := make([]*RevokedCertificate, len(pkixList.TBSCertList.RevokedCertificates))
  147. for i, pkixRevoked := range pkixList.TBSCertList.RevokedCertificates {
  148. revokedCerts[i] = parseRevokedCertificate(pkixRevoked, &errs)
  149. if revokedCerts[i] == nil {
  150. return nil, &errs
  151. }
  152. }
  153. certList := CertificateList{
  154. Raw: derBytes,
  155. TBSCertList: TBSCertList{
  156. Raw: pkixList.TBSCertList.Raw,
  157. Version: pkixList.TBSCertList.Version,
  158. Signature: pkixList.TBSCertList.Signature,
  159. Issuer: pkixList.TBSCertList.Issuer,
  160. ThisUpdate: pkixList.TBSCertList.ThisUpdate,
  161. NextUpdate: pkixList.TBSCertList.NextUpdate,
  162. RevokedCertificates: revokedCerts,
  163. Extensions: pkixList.TBSCertList.Extensions,
  164. CRLNumber: -1,
  165. BaseCRLNumber: -1,
  166. },
  167. SignatureAlgorithm: pkixList.SignatureAlgorithm,
  168. SignatureValue: pkixList.SignatureValue,
  169. }
  170. // Now crack out extensions.
  171. for _, e := range certList.TBSCertList.Extensions {
  172. if expectCritical, present := listExtCritical[e.Id.String()]; present {
  173. if e.Critical && !expectCritical {
  174. errs.AddID(ErrUnexpectedlyCriticalCertListExtension, e.Id)
  175. } else if !e.Critical && expectCritical {
  176. errs.AddID(ErrUnexpectedlyNonCriticalCertListExtension, e.Id)
  177. }
  178. }
  179. switch {
  180. case e.Id.Equal(OIDExtensionAuthorityKeyId):
  181. // RFC 5280 s5.2.1
  182. var a authKeyId
  183. if rest, err := asn1.Unmarshal(e.Value, &a); err != nil {
  184. errs.AddID(ErrInvalidCertListAuthKeyID, err)
  185. } else if len(rest) != 0 {
  186. errs.AddID(ErrTrailingCertListAuthKeyID)
  187. }
  188. certList.TBSCertList.AuthorityKeyID = a.Id
  189. case e.Id.Equal(OIDExtensionIssuerAltName):
  190. // RFC 5280 s5.2.2
  191. if err := parseGeneralNames(e.Value, &certList.TBSCertList.IssuerAltNames); err != nil {
  192. errs.AddID(ErrInvalidCertListIssuerAltName, err)
  193. }
  194. case e.Id.Equal(OIDExtensionCRLNumber):
  195. // RFC 5280 s5.2.3
  196. if rest, err := asn1.Unmarshal(e.Value, &certList.TBSCertList.CRLNumber); err != nil {
  197. errs.AddID(ErrInvalidCertListCRLNumber, err)
  198. } else if len(rest) != 0 {
  199. errs.AddID(ErrTrailingCertListCRLNumber)
  200. }
  201. if certList.TBSCertList.CRLNumber < 0 {
  202. errs.AddID(ErrNegativeCertListCRLNumber, certList.TBSCertList.CRLNumber)
  203. }
  204. case e.Id.Equal(OIDExtensionDeltaCRLIndicator):
  205. // RFC 5280 s5.2.4
  206. if rest, err := asn1.Unmarshal(e.Value, &certList.TBSCertList.BaseCRLNumber); err != nil {
  207. errs.AddID(ErrInvalidCertListDeltaCRL, err)
  208. } else if len(rest) != 0 {
  209. errs.AddID(ErrTrailingCertListDeltaCRL)
  210. }
  211. if certList.TBSCertList.BaseCRLNumber < 0 {
  212. errs.AddID(ErrNegativeCertListDeltaCRL, certList.TBSCertList.BaseCRLNumber)
  213. }
  214. case e.Id.Equal(OIDExtensionIssuingDistributionPoint):
  215. parseIssuingDistributionPoint(e.Value, &certList.TBSCertList.IssuingDistributionPoint, &certList.TBSCertList.IssuingDPFullNames, &errs)
  216. case e.Id.Equal(OIDExtensionFreshestCRL):
  217. // RFC 5280 s5.2.6
  218. if err := parseDistributionPoints(e.Value, &certList.TBSCertList.FreshestCRLDistributionPoint); err != nil {
  219. errs.AddID(ErrInvalidCertListFreshestCRL, err)
  220. return nil, err
  221. }
  222. case e.Id.Equal(OIDExtensionAuthorityInfoAccess):
  223. // RFC 5280 s5.2.7
  224. var aia []accessDescription
  225. if rest, err := asn1.Unmarshal(e.Value, &aia); err != nil {
  226. errs.AddID(ErrInvalidCertListAuthInfoAccess, err)
  227. } else if len(rest) != 0 {
  228. errs.AddID(ErrTrailingCertListAuthInfoAccess)
  229. }
  230. for _, v := range aia {
  231. // GeneralName: uniformResourceIdentifier [6] IA5String
  232. if v.Location.Tag != tagURI {
  233. continue
  234. }
  235. switch {
  236. case v.Method.Equal(OIDAuthorityInfoAccessOCSP):
  237. certList.TBSCertList.OCSPServer = append(certList.TBSCertList.OCSPServer, string(v.Location.Bytes))
  238. case v.Method.Equal(OIDAuthorityInfoAccessIssuers):
  239. certList.TBSCertList.IssuingCertificateURL = append(certList.TBSCertList.IssuingCertificateURL, string(v.Location.Bytes))
  240. }
  241. // TODO(drysdale): cope with more possibilities
  242. }
  243. default:
  244. if e.Critical {
  245. errs.AddID(ErrUnhandledCriticalCertListExtension, e.Id)
  246. }
  247. }
  248. }
  249. if errs.Fatal() {
  250. return nil, &errs
  251. }
  252. if errs.Empty() {
  253. return &certList, nil
  254. }
  255. return &certList, &errs
  256. }
  257. func parseIssuingDistributionPoint(data []byte, idp *IssuingDistributionPoint, name *GeneralNames, errs *Errors) {
  258. // RFC 5280 s5.2.5
  259. if rest, err := asn1.Unmarshal(data, idp); err != nil {
  260. errs.AddID(ErrInvalidCertListIssuingDP, err)
  261. } else if len(rest) != 0 {
  262. errs.AddID(ErrTrailingCertListIssuingDP)
  263. }
  264. typeCount := 0
  265. if idp.OnlyContainsUserCerts {
  266. typeCount++
  267. }
  268. if idp.OnlyContainsCACerts {
  269. typeCount++
  270. }
  271. if idp.OnlyContainsAttributeCerts {
  272. typeCount++
  273. }
  274. if typeCount > 1 {
  275. errs.AddID(ErrCertListIssuingDPMultipleTypes, idp.OnlyContainsUserCerts, idp.OnlyContainsCACerts, idp.OnlyContainsAttributeCerts)
  276. }
  277. for _, fn := range idp.DistributionPoint.FullName {
  278. if _, err := parseGeneralName(fn.FullBytes, name, false); err != nil {
  279. errs.AddID(ErrCertListIssuingDPInvalidFullName, err)
  280. }
  281. }
  282. }
  283. // RevokedCertificate represents the unnamed ASN.1 structure that makes up the
  284. // revokedCertificates member of the TBSCertList structure from RFC 5280, s5.1.
  285. // It has the same content as pkix.RevokedCertificate but the extensions are
  286. // included in a parsed format.
  287. type RevokedCertificate struct {
  288. pkix.RevokedCertificate
  289. // Cracked out extensions:
  290. RevocationReason RevocationReasonCode
  291. InvalidityDate time.Time
  292. Issuer GeneralNames
  293. }
  294. func parseRevokedCertificate(pkixRevoked pkix.RevokedCertificate, errs *Errors) *RevokedCertificate {
  295. result := RevokedCertificate{RevokedCertificate: pkixRevoked}
  296. for _, e := range pkixRevoked.Extensions {
  297. if expectCritical, present := certExtCritical[e.Id.String()]; present {
  298. if e.Critical && !expectCritical {
  299. errs.AddID(ErrUnexpectedlyCriticalRevokedCertExtension, e.Id)
  300. } else if !e.Critical && expectCritical {
  301. errs.AddID(ErrUnexpectedlyNonCriticalRevokedCertExtension, e.Id)
  302. }
  303. }
  304. switch {
  305. case e.Id.Equal(OIDExtensionCRLReasons):
  306. // RFC 5280, s5.3.1
  307. var reason asn1.Enumerated
  308. if rest, err := asn1.Unmarshal(e.Value, &reason); err != nil {
  309. errs.AddID(ErrInvalidRevocationReason, err)
  310. } else if len(rest) != 0 {
  311. errs.AddID(ErrTrailingRevocationReason)
  312. }
  313. result.RevocationReason = RevocationReasonCode(reason)
  314. case e.Id.Equal(OIDExtensionInvalidityDate):
  315. // RFC 5280, s5.3.2
  316. if rest, err := asn1.Unmarshal(e.Value, &result.InvalidityDate); err != nil {
  317. errs.AddID(ErrInvalidRevocationInvalidityDate, err)
  318. } else if len(rest) != 0 {
  319. errs.AddID(ErrTrailingRevocationInvalidityDate)
  320. }
  321. case e.Id.Equal(OIDExtensionCertificateIssuer):
  322. // RFC 5280, s5.3.3
  323. if err := parseGeneralNames(e.Value, &result.Issuer); err != nil {
  324. errs.AddID(ErrInvalidRevocationIssuer, err)
  325. }
  326. default:
  327. if e.Critical {
  328. errs.AddID(ErrUnhandledCriticalRevokedCertExtension, e.Id)
  329. }
  330. }
  331. }
  332. return &result
  333. }
  334. // CheckCertificateListSignature checks that the signature in crl is from c.
  335. func (c *Certificate) CheckCertificateListSignature(crl *CertificateList) error {
  336. algo := SignatureAlgorithmFromAI(crl.SignatureAlgorithm)
  337. return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign())
  338. }