Source file src/pkg/crypto/x509/pkix/pkix.go
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
5 // Package pkix contains shared, low level structures used for ASN.1 parsing
6 // and serialization of X.509 certificates, CRL and OCSP.
7 package pkix
8
9 import (
10 "encoding/asn1"
11 "math/big"
12 "time"
13 )
14
15 // AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
16 // 5280, section 4.1.1.2.
17 type AlgorithmIdentifier struct {
18 Algorithm asn1.ObjectIdentifier
19 Parameters asn1.RawValue `asn1:"optional"`
20 }
21
22 type RDNSequence []RelativeDistinguishedNameSET
23
24 type RelativeDistinguishedNameSET []AttributeTypeAndValue
25
26 // AttributeTypeAndValue mirrors the ASN.1 structure of the same name in
27 // http://tools.ietf.org/html/rfc5280#section-4.1.2.4
28 type AttributeTypeAndValue struct {
29 Type asn1.ObjectIdentifier
30 Value interface{}
31 }
32
33 // Extension represents the ASN.1 structure of the same name. See RFC
34 // 5280, section 4.2.
35 type Extension struct {
36 Id asn1.ObjectIdentifier
37 Critical bool `asn1:"optional"`
38 Value []byte
39 }
40
41 // Name represents an X.509 distinguished name. This only includes the common
42 // elements of a DN. Additional elements in the name are ignored.
43 type Name struct {
44 Country, Organization, OrganizationalUnit []string
45 Locality, Province []string
46 StreetAddress, PostalCode []string
47 SerialNumber, CommonName string
48
49 Names []AttributeTypeAndValue
50 }
51
52 func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
53 for _, rdn := range *rdns {
54 if len(rdn) == 0 {
55 continue
56 }
57 atv := rdn[0]
58 n.Names = append(n.Names, atv)
59 value, ok := atv.Value.(string)
60 if !ok {
61 continue
62 }
63
64 t := atv.Type
65 if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
66 switch t[3] {
67 case 3:
68 n.CommonName = value
69 case 5:
70 n.SerialNumber = value
71 case 6:
72 n.Country = append(n.Country, value)
73 case 7:
74 n.Locality = append(n.Locality, value)
75 case 8:
76 n.Province = append(n.Province, value)
77 case 9:
78 n.StreetAddress = append(n.StreetAddress, value)
79 case 10:
80 n.Organization = append(n.Organization, value)
81 case 11:
82 n.OrganizationalUnit = append(n.OrganizationalUnit, value)
83 case 17:
84 n.PostalCode = append(n.PostalCode, value)
85 }
86 }
87 }
88 }
89
90 var (
91 oidCountry = []int{2, 5, 4, 6}
92 oidOrganization = []int{2, 5, 4, 10}
93 oidOrganizationalUnit = []int{2, 5, 4, 11}
94 oidCommonName = []int{2, 5, 4, 3}
95 oidSerialNumber = []int{2, 5, 4, 5}
96 oidLocality = []int{2, 5, 4, 7}
97 oidProvince = []int{2, 5, 4, 8}
98 oidStreetAddress = []int{2, 5, 4, 9}
99 oidPostalCode = []int{2, 5, 4, 17}
100 )
101
102 // appendRDNs appends a relativeDistinguishedNameSET to the given RDNSequence
103 // and returns the new value. The relativeDistinguishedNameSET contains an
104 // attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
105 // search for AttributeTypeAndValue.
106 func appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
107 if len(values) == 0 {
108 return in
109 }
110
111 s := make([]AttributeTypeAndValue, len(values))
112 for i, value := range values {
113 s[i].Type = oid
114 s[i].Value = value
115 }
116
117 return append(in, s)
118 }
119
120 func (n Name) ToRDNSequence() (ret RDNSequence) {
121 ret = appendRDNs(ret, n.Country, oidCountry)
122 ret = appendRDNs(ret, n.Organization, oidOrganization)
123 ret = appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
124 ret = appendRDNs(ret, n.Locality, oidLocality)
125 ret = appendRDNs(ret, n.Province, oidProvince)
126 ret = appendRDNs(ret, n.StreetAddress, oidStreetAddress)
127 ret = appendRDNs(ret, n.PostalCode, oidPostalCode)
128 if len(n.CommonName) > 0 {
129 ret = appendRDNs(ret, []string{n.CommonName}, oidCommonName)
130 }
131 if len(n.SerialNumber) > 0 {
132 ret = appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
133 }
134
135 return ret
136 }
137
138 // CertificateList represents the ASN.1 structure of the same name. See RFC
139 // 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the
140 // signature.
141 type CertificateList struct {
142 TBSCertList TBSCertificateList
143 SignatureAlgorithm AlgorithmIdentifier
144 SignatureValue asn1.BitString
145 }
146
147 // HasExpired returns true iff now is past the expiry time of certList.
148 func (certList *CertificateList) HasExpired(now time.Time) bool {
149 return now.After(certList.TBSCertList.NextUpdate)
150 }
151
152 // TBSCertificateList represents the ASN.1 structure of the same name. See RFC
153 // 5280, section 5.1.
154 type TBSCertificateList struct {
155 Raw asn1.RawContent
156 Version int `asn1:"optional,default:2"`
157 Signature AlgorithmIdentifier
158 Issuer RDNSequence
159 ThisUpdate time.Time
160 NextUpdate time.Time
161 RevokedCertificates []RevokedCertificate `asn1:"optional"`
162 Extensions []Extension `asn1:"tag:0,optional,explicit"`
163 }
164
165 // RevokedCertificate represents the ASN.1 structure of the same name. See RFC
166 // 5280, section 5.1.
167 type RevokedCertificate struct {
168 SerialNumber *big.Int
169 RevocationTime time.Time
170 Extensions []Extension `asn1:"optional"`
171 }