crl_parser.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. package x509
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "math/big"
  7. "time"
  8. "unicode/utf16"
  9. "unicode/utf8"
  10. "github.com/zmap/zcrypto/cryptobyte"
  11. cryptobyte_asn1 "github.com/zmap/zcrypto/cryptobyte/asn1"
  12. "github.com/zmap/zcrypto/encoding/asn1"
  13. "github.com/zmap/zcrypto/x509/pkix"
  14. )
  15. const x509v2Version = 1
  16. // RevokedCertificate represents an entry in the revokedCertificates sequence of
  17. // a CRL.
  18. // STARTBLOCK: This type does not exist in upstream.
  19. type RevokedCertificate struct {
  20. // Raw contains the raw bytes of the revokedCertificates entry. It is set when
  21. // parsing a CRL; it is ignored when generating a CRL.
  22. Raw []byte
  23. // SerialNumber represents the serial number of a revoked certificate. It is
  24. // both used when creating a CRL and populated when parsing a CRL. It MUST NOT
  25. // be nil.
  26. SerialNumber *big.Int
  27. // RevocationTime represents the time at which the certificate was revoked. It
  28. // is both used when creating a CRL and populated when parsing a CRL. It MUST
  29. // NOT be nil.
  30. RevocationTime time.Time
  31. // ReasonCode represents the reason for revocation, using the integer enum
  32. // values specified in RFC 5280 Section 5.3.1. When creating a CRL, a value of
  33. // nil or zero will result in the reasonCode extension being omitted. When
  34. // parsing a CRL, a value of nil represents a no reasonCode extension, while a
  35. // value of 0 represents a reasonCode extension containing enum value 0 (this
  36. // SHOULD NOT happen, but can and does).
  37. ReasonCode *int
  38. // Extensions contains raw X.509 extensions. When creating a CRL, the
  39. // Extensions field is ignored, see ExtraExtensions.
  40. Extensions []pkix.Extension
  41. // ExtraExtensions contains any additional extensions to add directly to the
  42. // revokedCertificate entry. It is up to the caller to ensure that this field
  43. // does not contain any extensions which duplicate extensions created by this
  44. // package (currently, the reasonCode extension). The ExtraExtensions field is
  45. // not populated when parsing a CRL, see Extensions.
  46. ExtraExtensions []pkix.Extension
  47. }
  48. // ENDBLOCK
  49. // ParseRevocationList parses a X509 v2 Certificate Revocation List from the given
  50. // ASN.1 DER data.
  51. func ParseRevocationList(der []byte) (*RevocationList, error) {
  52. rl := &RevocationList{}
  53. input := cryptobyte.String(der)
  54. // we read the SEQUENCE including length and tag bytes so that
  55. // we can populate RevocationList.Raw, before unwrapping the
  56. // SEQUENCE so it can be operated on
  57. if !input.ReadASN1Element(&input, cryptobyte_asn1.SEQUENCE) {
  58. return nil, errors.New("x509: malformed crl")
  59. }
  60. rl.Raw = input
  61. if !input.ReadASN1(&input, cryptobyte_asn1.SEQUENCE) {
  62. return nil, errors.New("x509: malformed crl")
  63. }
  64. var tbs cryptobyte.String
  65. // do the same trick again as above to extract the raw
  66. // bytes for Certificate.RawTBSCertificate
  67. if !input.ReadASN1Element(&tbs, cryptobyte_asn1.SEQUENCE) {
  68. return nil, errors.New("x509: malformed tbs crl")
  69. }
  70. rl.RawTBSRevocationList = tbs
  71. if !tbs.ReadASN1(&tbs, cryptobyte_asn1.SEQUENCE) {
  72. return nil, errors.New("x509: malformed tbs crl")
  73. }
  74. var version int
  75. if !tbs.PeekASN1Tag(cryptobyte_asn1.INTEGER) {
  76. return nil, errors.New("x509: unsupported crl version")
  77. }
  78. if !tbs.ReadASN1Integer(&version) {
  79. return nil, errors.New("x509: malformed crl")
  80. }
  81. if version != x509v2Version {
  82. return nil, fmt.Errorf("x509: unsupported crl version: %d", version)
  83. }
  84. var sigAISeq cryptobyte.String
  85. if !tbs.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) {
  86. return nil, errors.New("x509: malformed signature algorithm identifier")
  87. }
  88. // Before parsing the inner algorithm identifier, extract
  89. // the outer algorithm identifier and make sure that they
  90. // match.
  91. var outerSigAISeq cryptobyte.String
  92. if !input.ReadASN1(&outerSigAISeq, cryptobyte_asn1.SEQUENCE) {
  93. return nil, errors.New("x509: malformed algorithm identifier")
  94. }
  95. if !bytes.Equal(outerSigAISeq, sigAISeq) {
  96. return nil, errors.New("x509: inner and outer signature algorithm identifiers don't match")
  97. }
  98. sigAI, err := parseAI(sigAISeq)
  99. if err != nil {
  100. return nil, err
  101. }
  102. rl.SignatureAlgorithm = getSignatureAlgorithmFromAI(sigAI)
  103. var signature asn1.BitString
  104. if !input.ReadASN1BitString(&signature) {
  105. return nil, errors.New("x509: malformed signature")
  106. }
  107. rl.Signature = signature.RightAlign()
  108. var issuerSeq cryptobyte.String
  109. if !tbs.ReadASN1Element(&issuerSeq, cryptobyte_asn1.SEQUENCE) {
  110. return nil, errors.New("x509: malformed issuer")
  111. }
  112. rl.RawIssuer = issuerSeq
  113. issuerRDNs, err := parseName(issuerSeq)
  114. if err != nil {
  115. return nil, err
  116. }
  117. rl.Issuer.FillFromRDNSequence(issuerRDNs)
  118. rl.ThisUpdate, err = parseTime(&tbs)
  119. if err != nil {
  120. return nil, err
  121. }
  122. if tbs.PeekASN1Tag(cryptobyte_asn1.GeneralizedTime) || tbs.PeekASN1Tag(cryptobyte_asn1.UTCTime) {
  123. rl.NextUpdate, err = parseTime(&tbs)
  124. if err != nil {
  125. return nil, err
  126. }
  127. }
  128. if tbs.PeekASN1Tag(cryptobyte_asn1.SEQUENCE) {
  129. // NOTE: The block does not exist in upstream.
  130. rcs := make([]RevokedCertificate, 0)
  131. // ENDBLOCK
  132. var revokedSeq cryptobyte.String
  133. if !tbs.ReadASN1(&revokedSeq, cryptobyte_asn1.SEQUENCE) {
  134. return nil, errors.New("x509: malformed crl")
  135. }
  136. for !revokedSeq.Empty() {
  137. var certSeq cryptobyte.String
  138. // NOTE: The block is different from upstream. Upstream: ReadASN1
  139. if !revokedSeq.ReadASN1Element(&certSeq, cryptobyte_asn1.SEQUENCE) {
  140. // ENDBLOCK
  141. return nil, errors.New("x509: malformed crl")
  142. }
  143. rc := RevokedCertificate{Raw: certSeq}
  144. if !certSeq.ReadASN1(&certSeq, cryptobyte_asn1.SEQUENCE) {
  145. return nil, errors.New("x509: malformed crl")
  146. }
  147. rc.SerialNumber = new(big.Int)
  148. if !certSeq.ReadASN1Integer(rc.SerialNumber) {
  149. return nil, errors.New("x509: malformed serial number")
  150. }
  151. rc.RevocationTime, err = parseTime(&certSeq)
  152. if err != nil {
  153. return nil, err
  154. }
  155. var extensions cryptobyte.String
  156. var present bool
  157. if !certSeq.ReadOptionalASN1(&extensions, &present, cryptobyte_asn1.SEQUENCE) {
  158. return nil, errors.New("x509: malformed extensions")
  159. }
  160. if present {
  161. for !extensions.Empty() {
  162. var extension cryptobyte.String
  163. if !extensions.ReadASN1(&extension, cryptobyte_asn1.SEQUENCE) {
  164. return nil, errors.New("x509: malformed extension")
  165. }
  166. ext, err := parseExtension(extension)
  167. if err != nil {
  168. return nil, err
  169. }
  170. // STARTBLOCK: This block does not exist in upstream.
  171. if ext.Id.Equal(oidExtensionReasonCode) {
  172. val := cryptobyte.String(ext.Value)
  173. rc.ReasonCode = new(int)
  174. if !val.ReadASN1Enum(rc.ReasonCode) {
  175. return nil, fmt.Errorf("x509: malformed reasonCode extension")
  176. }
  177. }
  178. // ENDBLOCK
  179. rc.Extensions = append(rc.Extensions, ext)
  180. }
  181. }
  182. // STARTBLOCK: The block does not exist in upstream.
  183. rcs = append(rcs, rc)
  184. // ENDBLOCK
  185. }
  186. rl.RevokedCertificates = rcs
  187. }
  188. var extensions cryptobyte.String
  189. var present bool
  190. if !tbs.ReadOptionalASN1(&extensions, &present, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) {
  191. return nil, errors.New("x509: malformed extensions")
  192. }
  193. if present {
  194. if !extensions.ReadASN1(&extensions, cryptobyte_asn1.SEQUENCE) {
  195. return nil, errors.New("x509: malformed extensions")
  196. }
  197. for !extensions.Empty() {
  198. var extension cryptobyte.String
  199. if !extensions.ReadASN1(&extension, cryptobyte_asn1.SEQUENCE) {
  200. return nil, errors.New("x509: malformed extension")
  201. }
  202. ext, err := parseExtension(extension)
  203. if err != nil {
  204. return nil, err
  205. }
  206. if ext.Id.Equal(oidExtensionAuthorityKeyId) {
  207. rl.AuthorityKeyId = ext.Value
  208. } else if ext.Id.Equal(oidExtensionCRLNumber) {
  209. value := cryptobyte.String(ext.Value)
  210. rl.Number = new(big.Int)
  211. if !value.ReadASN1Integer(rl.Number) {
  212. return nil, errors.New("x509: malformed crl number")
  213. }
  214. }
  215. rl.Extensions = append(rl.Extensions, ext)
  216. }
  217. }
  218. return rl, nil
  219. }
  220. // isPrintable reports whether the given b is in the ASN.1 PrintableString set.
  221. // This is a simplified version of encoding/asn1.isPrintable.
  222. func isPrintable(b byte) bool {
  223. return 'a' <= b && b <= 'z' ||
  224. 'A' <= b && b <= 'Z' ||
  225. '0' <= b && b <= '9' ||
  226. '\'' <= b && b <= ')' ||
  227. '+' <= b && b <= '/' ||
  228. b == ' ' ||
  229. b == ':' ||
  230. b == '=' ||
  231. b == '?' ||
  232. // This is technically not allowed in a PrintableString.
  233. // However, x509 certificates with wildcard strings don't
  234. // always use the correct string type so we permit it.
  235. b == '*' ||
  236. // This is not technically allowed either. However, not
  237. // only is it relatively common, but there are also a
  238. // handful of CA certificates that contain it. At least
  239. // one of which will not expire until 2027.
  240. b == '&'
  241. }
  242. // parseASN1String parses the ASN.1 string types T61String, PrintableString,
  243. // UTF8String, BMPString, IA5String, and NumericString. This is mostly copied
  244. // from the respective encoding/asn1.parse... methods, rather than just
  245. // increasing the API surface of that package.
  246. func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) {
  247. switch tag {
  248. case cryptobyte_asn1.T61String:
  249. return string(value), nil
  250. case cryptobyte_asn1.PrintableString:
  251. for _, b := range value {
  252. if !isPrintable(b) {
  253. return "", errors.New("invalid PrintableString")
  254. }
  255. }
  256. return string(value), nil
  257. case cryptobyte_asn1.UTF8String:
  258. if !utf8.Valid(value) {
  259. return "", errors.New("invalid UTF-8 string")
  260. }
  261. return string(value), nil
  262. case cryptobyte_asn1.Tag(asn1.TagBMPString):
  263. if len(value)%2 != 0 {
  264. return "", errors.New("invalid BMPString")
  265. }
  266. // Strip terminator if present.
  267. if l := len(value); l >= 2 && value[l-1] == 0 && value[l-2] == 0 {
  268. value = value[:l-2]
  269. }
  270. s := make([]uint16, 0, len(value)/2)
  271. for len(value) > 0 {
  272. s = append(s, uint16(value[0])<<8+uint16(value[1]))
  273. value = value[2:]
  274. }
  275. return string(utf16.Decode(s)), nil
  276. case cryptobyte_asn1.IA5String:
  277. s := string(value)
  278. if isIA5String(s) != nil {
  279. return "", errors.New("invalid IA5String")
  280. }
  281. return s, nil
  282. case cryptobyte_asn1.Tag(asn1.TagNumericString):
  283. for _, b := range value {
  284. if !('0' <= b && b <= '9' || b == ' ') {
  285. return "", errors.New("invalid NumericString")
  286. }
  287. }
  288. return string(value), nil
  289. }
  290. return "", fmt.Errorf("unsupported string type: %v", tag)
  291. }
  292. // parseName parses a DER encoded Name as defined in RFC 5280. We may
  293. // want to export this function in the future for use in crypto/tls.
  294. func parseName(raw cryptobyte.String) (*pkix.RDNSequence, error) {
  295. if !raw.ReadASN1(&raw, cryptobyte_asn1.SEQUENCE) {
  296. return nil, errors.New("x509: invalid RDNSequence")
  297. }
  298. var rdnSeq pkix.RDNSequence
  299. for !raw.Empty() {
  300. var rdnSet pkix.RelativeDistinguishedNameSET
  301. var set cryptobyte.String
  302. if !raw.ReadASN1(&set, cryptobyte_asn1.SET) {
  303. return nil, errors.New("x509: invalid RDNSequence")
  304. }
  305. for !set.Empty() {
  306. var atav cryptobyte.String
  307. if !set.ReadASN1(&atav, cryptobyte_asn1.SEQUENCE) {
  308. return nil, errors.New("x509: invalid RDNSequence: invalid attribute")
  309. }
  310. var attr pkix.AttributeTypeAndValue
  311. if !atav.ReadASN1ObjectIdentifier(&attr.Type) {
  312. return nil, errors.New("x509: invalid RDNSequence: invalid attribute type")
  313. }
  314. var rawValue cryptobyte.String
  315. var valueTag cryptobyte_asn1.Tag
  316. if !atav.ReadAnyASN1(&rawValue, &valueTag) {
  317. return nil, errors.New("x509: invalid RDNSequence: invalid attribute value")
  318. }
  319. var err error
  320. attr.Value, err = parseASN1String(valueTag, rawValue)
  321. if err != nil {
  322. return nil, fmt.Errorf("x509: invalid RDNSequence: invalid attribute value: %s", err)
  323. }
  324. rdnSet = append(rdnSet, attr)
  325. }
  326. rdnSeq = append(rdnSeq, rdnSet)
  327. }
  328. return &rdnSeq, nil
  329. }
  330. func parseAI(der cryptobyte.String) (pkix.AlgorithmIdentifier, error) {
  331. ai := pkix.AlgorithmIdentifier{}
  332. if !der.ReadASN1ObjectIdentifier(&ai.Algorithm) {
  333. return ai, errors.New("x509: malformed OID")
  334. }
  335. if der.Empty() {
  336. return ai, nil
  337. }
  338. var params cryptobyte.String
  339. var tag cryptobyte_asn1.Tag
  340. if !der.ReadAnyASN1Element(&params, &tag) {
  341. return ai, errors.New("x509: malformed parameters")
  342. }
  343. ai.Parameters.Tag = int(tag)
  344. ai.Parameters.FullBytes = params
  345. return ai, nil
  346. }
  347. func parseTime(der *cryptobyte.String) (time.Time, error) {
  348. var t time.Time
  349. switch {
  350. case der.PeekASN1Tag(cryptobyte_asn1.UTCTime):
  351. if !der.ReadASN1UTCTime(&t) {
  352. return t, errors.New("x509: malformed UTCTime")
  353. }
  354. case der.PeekASN1Tag(cryptobyte_asn1.GeneralizedTime):
  355. if !der.ReadASN1GeneralizedTime(&t) {
  356. return t, errors.New("x509: malformed GeneralizedTime")
  357. }
  358. default:
  359. return t, errors.New("x509: unsupported time format")
  360. }
  361. return t, nil
  362. }
  363. func parseExtension(der cryptobyte.String) (pkix.Extension, error) {
  364. var ext pkix.Extension
  365. if !der.ReadASN1ObjectIdentifier(&ext.Id) {
  366. return ext, errors.New("x509: malformed extension OID field")
  367. }
  368. if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) {
  369. if !der.ReadASN1Boolean(&ext.Critical) {
  370. return ext, errors.New("x509: malformed extension critical field")
  371. }
  372. }
  373. var val cryptobyte.String
  374. if !der.ReadASN1(&val, cryptobyte_asn1.OCTET_STRING) {
  375. return ext, errors.New("x509: malformed extension value field")
  376. }
  377. ext.Value = val
  378. return ext, nil
  379. }