// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This package parses X.509-encoded keys and certificates. package x509 import ( "asn1"; "big"; "container/vector"; "crypto/rsa"; "crypto/sha1"; "hash"; "os"; "strings"; "time"; ) // pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key. type pkcs1PrivateKey struct { Version int; N asn1.RawValue; E int; D asn1.RawValue; P asn1.RawValue; Q asn1.RawValue; } // rawValueIsInteger returns true iff the given ASN.1 RawValue is an INTEGER type. func rawValueIsInteger(raw *asn1.RawValue) bool { return raw.Class == 0 && raw.Tag == 2 && raw.IsCompound == false } // ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form. func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) { var priv pkcs1PrivateKey; rest, err := asn1.Unmarshal(&priv, der); if len(rest) > 0 { err = asn1.SyntaxError{"trailing data"}; return; } if err != nil { return } if !rawValueIsInteger(&priv.N) || !rawValueIsInteger(&priv.D) || !rawValueIsInteger(&priv.P) || !rawValueIsInteger(&priv.Q) { err = asn1.StructuralError{"tags don't match"}; return; } key = &rsa.PrivateKey{ PublicKey: rsa.PublicKey{ E: priv.E, N: new(big.Int).SetBytes(priv.N.Bytes), }, D: new(big.Int).SetBytes(priv.D.Bytes), P: new(big.Int).SetBytes(priv.P.Bytes), Q: new(big.Int).SetBytes(priv.Q.Bytes), }; err = key.Validate(); if err != nil { return nil, err } return; } // These structures reflect the ASN.1 structure of X.509 certificates.: type certificate struct { TBSCertificate tbsCertificate; SignatureAlgorithm algorithmIdentifier; SignatureValue asn1.BitString; } type tbsCertificate struct { Raw asn1.RawContent; Version int "optional,explicit,default:1,tag:0"; SerialNumber asn1.RawValue; SignatureAlgorithm algorithmIdentifier; Issuer rdnSequence; Validity validity; Subject rdnSequence; PublicKey publicKeyInfo; UniqueId asn1.BitString "optional,explicit,tag:1"; SubjectUniqueId asn1.BitString "optional,explicit,tag:2"; Extensions []extension "optional,explicit,tag:3"; } type algorithmIdentifier struct { Algorithm asn1.ObjectIdentifier; } type rdnSequence []relativeDistinguishedName type relativeDistinguishedName []attributeTypeAndValue type attributeTypeAndValue struct { Type asn1.ObjectIdentifier; Value interface{}; } type validity struct { NotBefore, NotAfter *time.Time; } type publicKeyInfo struct { Algorithm algorithmIdentifier; PublicKey asn1.BitString; } type extension struct { Id asn1.ObjectIdentifier; Critical bool "optional"; Value []byte; } // RFC 5280, 4.2.1.1 type authKeyId struct { Id []byte "optional,tag:0"; } type SignatureAlgorithm int const ( UnknownSignatureAlgorithm SignatureAlgorithm = iota; MD2WithRSA; MD5WithRSA; SHA1WithRSA; SHA256WithRSA; SHA384WithRSA; SHA512WithRSA; ) type PublicKeyAlgorithm int const ( UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota; RSA; ) // Name represents an X.509 distinguished name. This only includes the common // elements of a DN. Additional elements in the name are ignored. type Name struct { Country, Organization, OrganizationalUnit string; CommonName, SerialNumber, Locality string; Province, StreetAddress, PostalCode string; } func (n *Name) fillFromRDNSequence(rdns *rdnSequence) { for _, rdn := range *rdns { if len(rdn) == 0 { continue } atv := rdn[0]; value, ok := atv.Value.(string); if !ok { continue } t := atv.Type; if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { switch t[3] { case 3: n.CommonName = value case 5: n.SerialNumber = value case 6: n.Country = value case 7: n.Locality = value case 8: n.Province = value case 9: n.StreetAddress = value case 10: n.Organization = value case 11: n.OrganizationalUnit = value case 17: n.PostalCode = value } } } } func getSignatureAlgorithmFromOID(oid []int) SignatureAlgorithm { if len(oid) == 7 && oid[0] == 1 && oid[1] == 2 && oid[2] == 840 && oid[3] == 113549 && oid[4] == 1 && oid[5] == 1 { switch oid[6] { case 2: return MD2WithRSA case 4: return MD5WithRSA case 5: return SHA1WithRSA case 11: return SHA256WithRSA case 12: return SHA384WithRSA case 13: return SHA512WithRSA } } return UnknownSignatureAlgorithm; } func getPublicKeyAlgorithmFromOID(oid []int) PublicKeyAlgorithm { if len(oid) == 7 && oid[0] == 1 && oid[1] == 2 && oid[2] == 840 && oid[3] == 113549 && oid[4] == 1 && oid[5] == 1 { switch oid[6] { case 1: return RSA } } return UnknownPublicKeyAlgorithm; } // KeyUsage represents the set of actions that are valid for a given key. It's // a bitmap of the KeyUsage* constants. type KeyUsage int const ( KeyUsageDigitalSignature KeyUsage = 1 << iota; KeyUsageContentCommitment; KeyUsageKeyEncipherment; KeyUsageDataEncipherment; KeyUsageKeyAgreement; KeyUsageCertSign; KeyUsageCRLSign; KeyUsageEncipherOnly; KeyUsageDecipherOnly; ) // A Certificate represents an X.509 certificate. type Certificate struct { Raw []byte; // Raw ASN.1 DER contents. Signature []byte; SignatureAlgorithm SignatureAlgorithm; PublicKeyAlgorithm PublicKeyAlgorithm; PublicKey interface{}; Version int; SerialNumber []byte; Issuer Name; Subject Name; NotBefore, NotAfter *time.Time; // Validity bounds. KeyUsage KeyUsage; BasicConstraintsValid bool; // if true then the next two fields are valid. IsCA bool; MaxPathLen int; SubjectKeyId []byte; AuthorityKeyId []byte; // Subject Alternate Name values DNSNames []string; EmailAddresses []string; } // UnsupportedAlgorithmError results from attempting to perform an operation // that involves algorithms that are not currently implemented. type UnsupportedAlgorithmError struct{} func (UnsupportedAlgorithmError) String() string { return "cannot verify signature: algorithm unimplemented" } // ConstraintViolationError results when a requested usage is not permitted by // a certificate. For example: checking a signature when the public key isn't a // certificate signing key. type ConstraintViolationError struct{} func (ConstraintViolationError) String() string { return "invalid signature: parent certificate cannot sign this kind of certificate" } // CheckSignatureFrom verifies that the signature on c is a valid signature // from parent. func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) { // RFC 5280, 4.2.1.9: // "If the basic constraints extension is not present in a version 3 // certificate, or the extension is present but the cA boolean is not // asserted, then the certified public key MUST NOT be used to verify // certificate signatures." if parent.Version == 3 && !parent.BasicConstraintsValid || parent.BasicConstraintsValid && !parent.IsCA { return ConstraintViolationError{} } if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCertSign == 0 { return ConstraintViolationError{} } if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm { return UnsupportedAlgorithmError{} } // TODO(agl): don't ignore the path length constraint. var h hash.Hash; var hashType rsa.PKCS1v15Hash; switch c.SignatureAlgorithm { case SHA1WithRSA: h = sha1.New(); hashType = rsa.HashSHA1; default: return UnsupportedAlgorithmError{} } pub, ok := parent.PublicKey.(*rsa.PublicKey); if !ok { return UnsupportedAlgorithmError{} } h.Write(c.Raw); digest := h.Sum(); return rsa.VerifyPKCS1v15(pub, hashType, digest, c.Signature); } func matchHostnames(pattern, host string) bool { if len(pattern) == 0 || len(host) == 0 { return false } patternParts := strings.Split(pattern, ".", 0); hostParts := strings.Split(host, ".", 0); if len(patternParts) != len(hostParts) { return false } for i, patternPart := range patternParts { if patternPart == "*" { continue } if patternPart != hostParts[i] { return false } } return true; } // IsValidForHost returns true iff c is a valid certificate for the given host. func (c *Certificate) IsValidForHost(h string) bool { if len(c.DNSNames) > 0 { for _, match := range c.DNSNames { if matchHostnames(match, h) { return true } } // If Subject Alt Name is given, we ignore the common name. return false; } return matchHostnames(c.Subject.CommonName, h); } type UnhandledCriticalExtension struct{} func (h UnhandledCriticalExtension) String() string { return "unhandled critical extension" } type basicConstraints struct { IsCA bool "optional"; MaxPathLen int "optional"; } type rsaPublicKey struct { N asn1.RawValue; E int; } func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.Error) { switch algo { case RSA: p := new(rsaPublicKey); _, err := asn1.Unmarshal(p, asn1Data); if err != nil { return nil, err } if !rawValueIsInteger(&p.N) { return nil, asn1.StructuralError{"tags don't match"} } pub := &rsa.PublicKey{ E: p.E, N: new(big.Int).SetBytes(p.N.Bytes), }; return pub, nil; default: return nil, nil } panic("unreachable"); } func appendString(in []string, v string) (out []string) { if cap(in)-len(in) < 1 { out = make([]string, len(in)+1, len(in)*2+1); for i, v := range in { out[i] = v } } else { out = in[0 : len(in)+1] } out[len(in)] = v; return out; } func parseCertificate(in *certificate) (*Certificate, os.Error) { out := new(Certificate); out.Raw = in.TBSCertificate.Raw; out.Signature = in.SignatureValue.RightAlign(); out.SignatureAlgorithm = getSignatureAlgorithmFromOID(in.TBSCertificate.SignatureAlgorithm.Algorithm); out.PublicKeyAlgorithm = getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm); var err os.Error; out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, in.TBSCertificate.PublicKey.PublicKey.RightAlign()); if err != nil { return nil, err } out.Version = in.TBSCertificate.Version; out.SerialNumber = in.TBSCertificate.SerialNumber.Bytes; out.Issuer.fillFromRDNSequence(&in.TBSCertificate.Issuer); out.Subject.fillFromRDNSequence(&in.TBSCertificate.Subject); out.NotBefore = in.TBSCertificate.Validity.NotBefore; out.NotAfter = in.TBSCertificate.Validity.NotAfter; for _, e := range in.TBSCertificate.Extensions { if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { switch e.Id[3] { case 15: // RFC 5280, 4.2.1.3 var usageBits asn1.BitString; _, err := asn1.Unmarshal(&usageBits, e.Value); if err == nil { var usage int; for i := 0; i < 9; i++ { if usageBits.At(i) != 0 { usage |= 1 << uint(i) } } out.KeyUsage = KeyUsage(usage); continue; } case 19: // RFC 5280, 4.2.1.9 var constriants basicConstraints; _, err := asn1.Unmarshal(&constriants, e.Value); if err == nil { out.BasicConstraintsValid = true; out.IsCA = constriants.IsCA; out.MaxPathLen = constriants.MaxPathLen; continue; } case 17: // RFC 5280, 4.2.1.6 // SubjectAltName ::= GeneralNames // // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName // // GeneralName ::= CHOICE { // otherName [0] OtherName, // rfc822Name [1] IA5String, // dNSName [2] IA5String, // x400Address [3] ORAddress, // directoryName [4] Name, // ediPartyName [5] EDIPartyName, // uniformResourceIdentifier [6] IA5String, // iPAddress [7] OCTET STRING, // registeredID [8] OBJECT IDENTIFIER } var seq asn1.RawValue; _, err := asn1.Unmarshal(&seq, e.Value); if err != nil { return nil, err } if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { return nil, asn1.StructuralError{"bad SAN sequence"} } parsedName := false; rest := seq.Bytes; for len(rest) > 0 { var v asn1.RawValue; rest, err = asn1.Unmarshal(&v, rest); if err != nil { return nil, err } switch v.Tag { case 1: out.EmailAddresses = appendString(out.EmailAddresses, string(v.Bytes)); parsedName = true; case 2: out.DNSNames = appendString(out.DNSNames, string(v.Bytes)); parsedName = true; } } if parsedName { continue } // If we didn't parse any of the names then we // fall through to the critical check below. case 35: // RFC 5280, 4.2.1.1 var a authKeyId; _, err = asn1.Unmarshal(&a, e.Value); if err != nil { return nil, err } out.AuthorityKeyId = a.Id; continue; case 14: // RFC 5280, 4.2.1.2 out.SubjectKeyId = e.Value; continue; } } if e.Critical { return out, UnhandledCriticalExtension{} } } return out, nil; } // ParseCertificate parses a single certificate from the given ASN.1 DER data. func ParseCertificate(asn1Data []byte) (*Certificate, os.Error) { var cert certificate; rest, err := asn1.Unmarshal(&cert, asn1Data); if err != nil { return nil, err } if len(rest) > 0 { return nil, asn1.SyntaxError{"trailing data"} } return parseCertificate(&cert); } // ParseCertificates parses one or more certificates from the given ASN.1 DER // data. The certificates must be concatenated with no intermediate padding. func ParseCertificates(asn1Data []byte) ([]*Certificate, os.Error) { v := new(vector.Vector); for len(asn1Data) > 0 { cert := new(certificate); var err os.Error; asn1Data, err = asn1.Unmarshal(cert, asn1Data); if err != nil { return nil, err } v.Push(cert); } ret := make([]*Certificate, v.Len()); for i := 0; i < v.Len(); i++ { cert, err := parseCertificate(v.At(i).(*certificate)); if err != nil { return nil, err } ret[i] = cert; } return ret, nil; }