pkix.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright 2011 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. // Package pkix contains shared, low level structures used for ASN.1 parsing
  5. // and serialization of X.509 certificates, CRL and OCSP.
  6. package pkix
  7. import (
  8. // START CT CHANGES
  9. "encoding/hex"
  10. "fmt"
  11. "github.com/google/certificate-transparency-go/asn1"
  12. // END CT CHANGES
  13. "math/big"
  14. "time"
  15. )
  16. // AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
  17. // 5280, section 4.1.1.2.
  18. type AlgorithmIdentifier struct {
  19. Algorithm asn1.ObjectIdentifier
  20. Parameters asn1.RawValue `asn1:"optional"`
  21. }
  22. type RDNSequence []RelativeDistinguishedNameSET
  23. var attributeTypeNames = map[string]string{
  24. "2.5.4.6": "C",
  25. "2.5.4.10": "O",
  26. "2.5.4.11": "OU",
  27. "2.5.4.3": "CN",
  28. "2.5.4.5": "SERIALNUMBER",
  29. "2.5.4.7": "L",
  30. "2.5.4.8": "ST",
  31. "2.5.4.9": "STREET",
  32. "2.5.4.17": "POSTALCODE",
  33. }
  34. // String returns a string representation of the sequence r,
  35. // roughly following the RFC 2253 Distinguished Names syntax.
  36. func (r RDNSequence) String() string {
  37. s := ""
  38. for i := 0; i < len(r); i++ {
  39. rdn := r[len(r)-1-i]
  40. if i > 0 {
  41. s += ","
  42. }
  43. for j, tv := range rdn {
  44. if j > 0 {
  45. s += "+"
  46. }
  47. oidString := tv.Type.String()
  48. typeName, ok := attributeTypeNames[oidString]
  49. if !ok {
  50. derBytes, err := asn1.Marshal(tv.Value)
  51. if err == nil {
  52. s += oidString + "=#" + hex.EncodeToString(derBytes)
  53. continue // No value escaping necessary.
  54. }
  55. typeName = oidString
  56. }
  57. valueString := fmt.Sprint(tv.Value)
  58. escaped := make([]rune, 0, len(valueString))
  59. for k, c := range valueString {
  60. escape := false
  61. switch c {
  62. case ',', '+', '"', '\\', '<', '>', ';':
  63. escape = true
  64. case ' ':
  65. escape = k == 0 || k == len(valueString)-1
  66. case '#':
  67. escape = k == 0
  68. }
  69. if escape {
  70. escaped = append(escaped, '\\', c)
  71. } else {
  72. escaped = append(escaped, c)
  73. }
  74. }
  75. s += typeName + "=" + string(escaped)
  76. }
  77. }
  78. return s
  79. }
  80. type RelativeDistinguishedNameSET []AttributeTypeAndValue
  81. // AttributeTypeAndValue mirrors the ASN.1 structure of the same name in
  82. // http://tools.ietf.org/html/rfc5280#section-4.1.2.4
  83. type AttributeTypeAndValue struct {
  84. Type asn1.ObjectIdentifier
  85. Value interface{}
  86. }
  87. // AttributeTypeAndValueSET represents a set of ASN.1 sequences of
  88. // AttributeTypeAndValue sequences from RFC 2986 (PKCS #10).
  89. type AttributeTypeAndValueSET struct {
  90. Type asn1.ObjectIdentifier
  91. Value [][]AttributeTypeAndValue `asn1:"set"`
  92. }
  93. // Extension represents the ASN.1 structure of the same name. See RFC
  94. // 5280, section 4.2.
  95. type Extension struct {
  96. Id asn1.ObjectIdentifier
  97. Critical bool `asn1:"optional"`
  98. Value []byte
  99. }
  100. // Name represents an X.509 distinguished name. This only includes the common
  101. // elements of a DN. When parsing, all elements are stored in Names and
  102. // non-standard elements can be extracted from there. When marshaling, elements
  103. // in ExtraNames are appended and override other values with the same OID.
  104. type Name struct {
  105. Country, Organization, OrganizationalUnit []string
  106. Locality, Province []string
  107. StreetAddress, PostalCode []string
  108. SerialNumber, CommonName string
  109. Names []AttributeTypeAndValue
  110. ExtraNames []AttributeTypeAndValue
  111. }
  112. func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
  113. for _, rdn := range *rdns {
  114. if len(rdn) == 0 {
  115. continue
  116. }
  117. for _, atv := range rdn {
  118. n.Names = append(n.Names, atv)
  119. value, ok := atv.Value.(string)
  120. if !ok {
  121. continue
  122. }
  123. t := atv.Type
  124. if len(t) == 4 && t[0] == OIDAttribute[0] && t[1] == OIDAttribute[1] && t[2] == OIDAttribute[2] {
  125. switch t[3] {
  126. case OIDCommonName[3]:
  127. n.CommonName = value
  128. case OIDSerialNumber[3]:
  129. n.SerialNumber = value
  130. case OIDCountry[3]:
  131. n.Country = append(n.Country, value)
  132. case OIDLocality[3]:
  133. n.Locality = append(n.Locality, value)
  134. case OIDProvince[3]:
  135. n.Province = append(n.Province, value)
  136. case OIDStreetAddress[3]:
  137. n.StreetAddress = append(n.StreetAddress, value)
  138. case OIDOrganization[3]:
  139. n.Organization = append(n.Organization, value)
  140. case OIDOrganizationalUnit[3]:
  141. n.OrganizationalUnit = append(n.OrganizationalUnit, value)
  142. case OIDPostalCode[3]:
  143. n.PostalCode = append(n.PostalCode, value)
  144. }
  145. }
  146. }
  147. }
  148. }
  149. var (
  150. OIDAttribute = asn1.ObjectIdentifier{2, 5, 4}
  151. OIDCountry = asn1.ObjectIdentifier{2, 5, 4, 6}
  152. OIDOrganization = asn1.ObjectIdentifier{2, 5, 4, 10}
  153. OIDOrganizationalUnit = asn1.ObjectIdentifier{2, 5, 4, 11}
  154. OIDCommonName = asn1.ObjectIdentifier{2, 5, 4, 3}
  155. OIDSerialNumber = asn1.ObjectIdentifier{2, 5, 4, 5}
  156. OIDLocality = asn1.ObjectIdentifier{2, 5, 4, 7}
  157. OIDProvince = asn1.ObjectIdentifier{2, 5, 4, 8}
  158. OIDStreetAddress = asn1.ObjectIdentifier{2, 5, 4, 9}
  159. OIDPostalCode = asn1.ObjectIdentifier{2, 5, 4, 17}
  160. OIDPseudonym = asn1.ObjectIdentifier{2, 5, 4, 65}
  161. OIDTitle = asn1.ObjectIdentifier{2, 5, 4, 12}
  162. OIDDnQualifier = asn1.ObjectIdentifier{2, 5, 4, 46}
  163. OIDName = asn1.ObjectIdentifier{2, 5, 4, 41}
  164. OIDSurname = asn1.ObjectIdentifier{2, 5, 4, 4}
  165. OIDGivenName = asn1.ObjectIdentifier{2, 5, 4, 42}
  166. OIDInitials = asn1.ObjectIdentifier{2, 5, 4, 43}
  167. OIDGenerationQualifier = asn1.ObjectIdentifier{2, 5, 4, 44}
  168. )
  169. // appendRDNs appends a relativeDistinguishedNameSET to the given RDNSequence
  170. // and returns the new value. The relativeDistinguishedNameSET contains an
  171. // attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
  172. // search for AttributeTypeAndValue.
  173. func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
  174. if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) {
  175. return in
  176. }
  177. s := make([]AttributeTypeAndValue, len(values))
  178. for i, value := range values {
  179. s[i].Type = oid
  180. s[i].Value = value
  181. }
  182. return append(in, s)
  183. }
  184. func (n Name) ToRDNSequence() (ret RDNSequence) {
  185. ret = n.appendRDNs(ret, n.Country, OIDCountry)
  186. ret = n.appendRDNs(ret, n.Province, OIDProvince)
  187. ret = n.appendRDNs(ret, n.Locality, OIDLocality)
  188. ret = n.appendRDNs(ret, n.StreetAddress, OIDStreetAddress)
  189. ret = n.appendRDNs(ret, n.PostalCode, OIDPostalCode)
  190. ret = n.appendRDNs(ret, n.Organization, OIDOrganization)
  191. ret = n.appendRDNs(ret, n.OrganizationalUnit, OIDOrganizationalUnit)
  192. if len(n.CommonName) > 0 {
  193. ret = n.appendRDNs(ret, []string{n.CommonName}, OIDCommonName)
  194. }
  195. if len(n.SerialNumber) > 0 {
  196. ret = n.appendRDNs(ret, []string{n.SerialNumber}, OIDSerialNumber)
  197. }
  198. for _, atv := range n.ExtraNames {
  199. ret = append(ret, []AttributeTypeAndValue{atv})
  200. }
  201. return ret
  202. }
  203. // String returns the string form of n, roughly following
  204. // the RFC 2253 Distinguished Names syntax.
  205. func (n Name) String() string {
  206. return n.ToRDNSequence().String()
  207. }
  208. // oidInAttributeTypeAndValue returns whether a type with the given OID exists
  209. // in atv.
  210. func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAndValue) bool {
  211. for _, a := range atv {
  212. if a.Type.Equal(oid) {
  213. return true
  214. }
  215. }
  216. return false
  217. }
  218. // CertificateList represents the ASN.1 structure of the same name. See RFC
  219. // 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the
  220. // signature.
  221. type CertificateList struct {
  222. TBSCertList TBSCertificateList
  223. SignatureAlgorithm AlgorithmIdentifier
  224. SignatureValue asn1.BitString
  225. }
  226. // HasExpired reports whether certList should have been updated by now.
  227. func (certList *CertificateList) HasExpired(now time.Time) bool {
  228. return !now.Before(certList.TBSCertList.NextUpdate)
  229. }
  230. // TBSCertificateList represents the ASN.1 structure TBSCertList. See RFC
  231. // 5280, section 5.1.
  232. type TBSCertificateList struct {
  233. Raw asn1.RawContent
  234. Version int `asn1:"optional,default:0"`
  235. Signature AlgorithmIdentifier
  236. Issuer RDNSequence
  237. ThisUpdate time.Time
  238. NextUpdate time.Time `asn1:"optional"`
  239. RevokedCertificates []RevokedCertificate `asn1:"optional"`
  240. Extensions []Extension `asn1:"tag:0,optional,explicit"`
  241. }
  242. // RevokedCertificate represents the unnamed ASN.1 structure that makes up the
  243. // revokedCertificates member of the TBSCertList structure. See RFC
  244. // 5280, section 5.1.
  245. type RevokedCertificate struct {
  246. SerialNumber *big.Int
  247. RevocationTime time.Time
  248. Extensions []Extension `asn1:"optional"`
  249. }