...

Source file src/crypto/x509/pkix/pkix.go

Documentation: crypto/x509/pkix

		 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  	"encoding/hex"
		12  	"fmt"
		13  	"math/big"
		14  	"time"
		15  )
		16  
		17  // AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
		18  // 5280, section 4.1.1.2.
		19  type AlgorithmIdentifier struct {
		20  	Algorithm	asn1.ObjectIdentifier
		21  	Parameters asn1.RawValue `asn1:"optional"`
		22  }
		23  
		24  type RDNSequence []RelativeDistinguishedNameSET
		25  
		26  var attributeTypeNames = map[string]string{
		27  	"2.5.4.6":	"C",
		28  	"2.5.4.10": "O",
		29  	"2.5.4.11": "OU",
		30  	"2.5.4.3":	"CN",
		31  	"2.5.4.5":	"SERIALNUMBER",
		32  	"2.5.4.7":	"L",
		33  	"2.5.4.8":	"ST",
		34  	"2.5.4.9":	"STREET",
		35  	"2.5.4.17": "POSTALCODE",
		36  }
		37  
		38  // String returns a string representation of the sequence r,
		39  // roughly following the RFC 2253 Distinguished Names syntax.
		40  func (r RDNSequence) String() string {
		41  	s := ""
		42  	for i := 0; i < len(r); i++ {
		43  		rdn := r[len(r)-1-i]
		44  		if i > 0 {
		45  			s += ","
		46  		}
		47  		for j, tv := range rdn {
		48  			if j > 0 {
		49  				s += "+"
		50  			}
		51  
		52  			oidString := tv.Type.String()
		53  			typeName, ok := attributeTypeNames[oidString]
		54  			if !ok {
		55  				derBytes, err := asn1.Marshal(tv.Value)
		56  				if err == nil {
		57  					s += oidString + "=#" + hex.EncodeToString(derBytes)
		58  					continue // No value escaping necessary.
		59  				}
		60  
		61  				typeName = oidString
		62  			}
		63  
		64  			valueString := fmt.Sprint(tv.Value)
		65  			escaped := make([]rune, 0, len(valueString))
		66  
		67  			for k, c := range valueString {
		68  				escape := false
		69  
		70  				switch c {
		71  				case ',', '+', '"', '\\', '<', '>', ';':
		72  					escape = true
		73  
		74  				case ' ':
		75  					escape = k == 0 || k == len(valueString)-1
		76  
		77  				case '#':
		78  					escape = k == 0
		79  				}
		80  
		81  				if escape {
		82  					escaped = append(escaped, '\\', c)
		83  				} else {
		84  					escaped = append(escaped, c)
		85  				}
		86  			}
		87  
		88  			s += typeName + "=" + string(escaped)
		89  		}
		90  	}
		91  
		92  	return s
		93  }
		94  
		95  type RelativeDistinguishedNameSET []AttributeTypeAndValue
		96  
		97  // AttributeTypeAndValue mirrors the ASN.1 structure of the same name in
		98  // RFC 5280, Section 4.1.2.4.
		99  type AttributeTypeAndValue struct {
	 100  	Type	asn1.ObjectIdentifier
	 101  	Value interface{}
	 102  }
	 103  
	 104  // AttributeTypeAndValueSET represents a set of ASN.1 sequences of
	 105  // AttributeTypeAndValue sequences from RFC 2986 (PKCS #10).
	 106  type AttributeTypeAndValueSET struct {
	 107  	Type	asn1.ObjectIdentifier
	 108  	Value [][]AttributeTypeAndValue `asn1:"set"`
	 109  }
	 110  
	 111  // Extension represents the ASN.1 structure of the same name. See RFC
	 112  // 5280, section 4.2.
	 113  type Extension struct {
	 114  	Id			 asn1.ObjectIdentifier
	 115  	Critical bool `asn1:"optional"`
	 116  	Value		[]byte
	 117  }
	 118  
	 119  // Name represents an X.509 distinguished name. This only includes the common
	 120  // elements of a DN. Note that Name is only an approximation of the X.509
	 121  // structure. If an accurate representation is needed, asn1.Unmarshal the raw
	 122  // subject or issuer as an RDNSequence.
	 123  type Name struct {
	 124  	Country, Organization, OrganizationalUnit []string
	 125  	Locality, Province												[]string
	 126  	StreetAddress, PostalCode								 []string
	 127  	SerialNumber, CommonName									string
	 128  
	 129  	// Names contains all parsed attributes. When parsing distinguished names,
	 130  	// this can be used to extract non-standard attributes that are not parsed
	 131  	// by this package. When marshaling to RDNSequences, the Names field is
	 132  	// ignored, see ExtraNames.
	 133  	Names []AttributeTypeAndValue
	 134  
	 135  	// ExtraNames contains attributes to be copied, raw, into any marshaled
	 136  	// distinguished names. Values override any attributes with the same OID.
	 137  	// The ExtraNames field is not populated when parsing, see Names.
	 138  	ExtraNames []AttributeTypeAndValue
	 139  }
	 140  
	 141  // FillFromRDNSequence populates n from the provided RDNSequence.
	 142  // Multi-entry RDNs are flattened, all entries are added to the
	 143  // relevant n fields, and the grouping is not preserved.
	 144  func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
	 145  	for _, rdn := range *rdns {
	 146  		if len(rdn) == 0 {
	 147  			continue
	 148  		}
	 149  
	 150  		for _, atv := range rdn {
	 151  			n.Names = append(n.Names, atv)
	 152  			value, ok := atv.Value.(string)
	 153  			if !ok {
	 154  				continue
	 155  			}
	 156  
	 157  			t := atv.Type
	 158  			if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
	 159  				switch t[3] {
	 160  				case 3:
	 161  					n.CommonName = value
	 162  				case 5:
	 163  					n.SerialNumber = value
	 164  				case 6:
	 165  					n.Country = append(n.Country, value)
	 166  				case 7:
	 167  					n.Locality = append(n.Locality, value)
	 168  				case 8:
	 169  					n.Province = append(n.Province, value)
	 170  				case 9:
	 171  					n.StreetAddress = append(n.StreetAddress, value)
	 172  				case 10:
	 173  					n.Organization = append(n.Organization, value)
	 174  				case 11:
	 175  					n.OrganizationalUnit = append(n.OrganizationalUnit, value)
	 176  				case 17:
	 177  					n.PostalCode = append(n.PostalCode, value)
	 178  				}
	 179  			}
	 180  		}
	 181  	}
	 182  }
	 183  
	 184  var (
	 185  	oidCountry						= []int{2, 5, 4, 6}
	 186  	oidOrganization			 = []int{2, 5, 4, 10}
	 187  	oidOrganizationalUnit = []int{2, 5, 4, 11}
	 188  	oidCommonName				 = []int{2, 5, 4, 3}
	 189  	oidSerialNumber			 = []int{2, 5, 4, 5}
	 190  	oidLocality					 = []int{2, 5, 4, 7}
	 191  	oidProvince					 = []int{2, 5, 4, 8}
	 192  	oidStreetAddress			= []int{2, 5, 4, 9}
	 193  	oidPostalCode				 = []int{2, 5, 4, 17}
	 194  )
	 195  
	 196  // appendRDNs appends a relativeDistinguishedNameSET to the given RDNSequence
	 197  // and returns the new value. The relativeDistinguishedNameSET contains an
	 198  // attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
	 199  // search for AttributeTypeAndValue.
	 200  func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
	 201  	if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) {
	 202  		return in
	 203  	}
	 204  
	 205  	s := make([]AttributeTypeAndValue, len(values))
	 206  	for i, value := range values {
	 207  		s[i].Type = oid
	 208  		s[i].Value = value
	 209  	}
	 210  
	 211  	return append(in, s)
	 212  }
	 213  
	 214  // ToRDNSequence converts n into a single RDNSequence. The following
	 215  // attributes are encoded as multi-value RDNs:
	 216  //
	 217  //	- Country
	 218  //	- Organization
	 219  //	- OrganizationalUnit
	 220  //	- Locality
	 221  //	- Province
	 222  //	- StreetAddress
	 223  //	- PostalCode
	 224  //
	 225  // Each ExtraNames entry is encoded as an individual RDN.
	 226  func (n Name) ToRDNSequence() (ret RDNSequence) {
	 227  	ret = n.appendRDNs(ret, n.Country, oidCountry)
	 228  	ret = n.appendRDNs(ret, n.Province, oidProvince)
	 229  	ret = n.appendRDNs(ret, n.Locality, oidLocality)
	 230  	ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress)
	 231  	ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode)
	 232  	ret = n.appendRDNs(ret, n.Organization, oidOrganization)
	 233  	ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
	 234  	if len(n.CommonName) > 0 {
	 235  		ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName)
	 236  	}
	 237  	if len(n.SerialNumber) > 0 {
	 238  		ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
	 239  	}
	 240  	for _, atv := range n.ExtraNames {
	 241  		ret = append(ret, []AttributeTypeAndValue{atv})
	 242  	}
	 243  
	 244  	return ret
	 245  }
	 246  
	 247  // String returns the string form of n, roughly following
	 248  // the RFC 2253 Distinguished Names syntax.
	 249  func (n Name) String() string {
	 250  	var rdns RDNSequence
	 251  	// If there are no ExtraNames, surface the parsed value (all entries in
	 252  	// Names) instead.
	 253  	if n.ExtraNames == nil {
	 254  		for _, atv := range n.Names {
	 255  			t := atv.Type
	 256  			if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
	 257  				switch t[3] {
	 258  				case 3, 5, 6, 7, 8, 9, 10, 11, 17:
	 259  					// These attributes were already parsed into named fields.
	 260  					continue
	 261  				}
	 262  			}
	 263  			// Place non-standard parsed values at the beginning of the sequence
	 264  			// so they will be at the end of the string. See Issue 39924.
	 265  			rdns = append(rdns, []AttributeTypeAndValue{atv})
	 266  		}
	 267  	}
	 268  	rdns = append(rdns, n.ToRDNSequence()...)
	 269  	return rdns.String()
	 270  }
	 271  
	 272  // oidInAttributeTypeAndValue reports whether a type with the given OID exists
	 273  // in atv.
	 274  func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAndValue) bool {
	 275  	for _, a := range atv {
	 276  		if a.Type.Equal(oid) {
	 277  			return true
	 278  		}
	 279  	}
	 280  	return false
	 281  }
	 282  
	 283  // CertificateList represents the ASN.1 structure of the same name. See RFC
	 284  // 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the
	 285  // signature.
	 286  type CertificateList struct {
	 287  	TBSCertList				TBSCertificateList
	 288  	SignatureAlgorithm AlgorithmIdentifier
	 289  	SignatureValue		 asn1.BitString
	 290  }
	 291  
	 292  // HasExpired reports whether certList should have been updated by now.
	 293  func (certList *CertificateList) HasExpired(now time.Time) bool {
	 294  	return !now.Before(certList.TBSCertList.NextUpdate)
	 295  }
	 296  
	 297  // TBSCertificateList represents the ASN.1 structure of the same name. See RFC
	 298  // 5280, section 5.1.
	 299  type TBSCertificateList struct {
	 300  	Raw								 asn1.RawContent
	 301  	Version						 int `asn1:"optional,default:0"`
	 302  	Signature					 AlgorithmIdentifier
	 303  	Issuer							RDNSequence
	 304  	ThisUpdate					time.Time
	 305  	NextUpdate					time.Time						`asn1:"optional"`
	 306  	RevokedCertificates []RevokedCertificate `asn1:"optional"`
	 307  	Extensions					[]Extension					`asn1:"tag:0,optional,explicit"`
	 308  }
	 309  
	 310  // RevokedCertificate represents the ASN.1 structure of the same name. See RFC
	 311  // 5280, section 5.1.
	 312  type RevokedCertificate struct {
	 313  	SerialNumber	 *big.Int
	 314  	RevocationTime time.Time
	 315  	Extensions		 []Extension `asn1:"optional"`
	 316  }
	 317  

View as plain text