summaryrefslogtreecommitdiff
path: root/libgo/go/crypto/x509/x509.go
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-05-11 11:13:27 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-05-11 11:13:27 +0000
commitc41143fb1d63596ff2a0f6da741b4bae73b8be16 (patch)
treed70c0763693cfef7bc877f21e079986944261a5f /libgo/go/crypto/x509/x509.go
parenteb0badc13724022c8828a55e516d0eecdc487cc3 (diff)
downloadgcc-c41143fb1d63596ff2a0f6da741b4bae73b8be16.tar.gz
2011-05-11 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 173647 using svnmerge git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@173652 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/crypto/x509/x509.go')
-rw-r--r--libgo/go/crypto/x509/x509.go176
1 files changed, 163 insertions, 13 deletions
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index 6199e8db9f5..6825030d6f9 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -9,6 +9,7 @@ import (
"asn1"
"big"
"container/vector"
+ "crypto"
"crypto/rsa"
"crypto/sha1"
"hash"
@@ -53,20 +54,21 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
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),
+ key = new(rsa.PrivateKey)
+ key.PublicKey = rsa.PublicKey{
+ E: priv.E,
+ N: new(big.Int).SetBytes(priv.N.Bytes),
}
+ key.D = new(big.Int).SetBytes(priv.D.Bytes)
+ key.P = new(big.Int).SetBytes(priv.P.Bytes)
+ key.Q = new(big.Int).SetBytes(priv.Q.Bytes)
+
err = key.Validate()
if err != nil {
return nil, err
}
+
return
}
@@ -303,6 +305,42 @@ const (
KeyUsageDecipherOnly
)
+// RFC 5280, 4.2.1.12 Extended Key Usage
+//
+// anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }
+//
+// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
+//
+// id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
+// id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
+// id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
+// id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
+// id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
+// id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
+var (
+ oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
+ oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
+ oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
+ oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
+ oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
+ oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
+ oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
+)
+
+// ExtKeyUsage represents an extended set of actions that are valid for a given key.
+// Each of the ExtKeyUsage* constants define a unique action.
+type ExtKeyUsage int
+
+const (
+ ExtKeyUsageAny ExtKeyUsage = iota
+ ExtKeyUsageServerAuth
+ ExtKeyUsageClientAuth
+ ExtKeyUsageCodeSigning
+ ExtKeyUsageEmailProtection
+ ExtKeyUsageTimeStamping
+ ExtKeyUsageOCSPSigning
+)
+
// A Certificate represents an X.509 certificate.
type Certificate struct {
Raw []byte // Raw ASN.1 DER contents.
@@ -319,6 +357,9 @@ type Certificate struct {
NotBefore, NotAfter *time.Time // Validity bounds.
KeyUsage KeyUsage
+ ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages.
+ UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package.
+
BasicConstraintsValid bool // if true then the next two fields are valid.
IsCA bool
MaxPathLen int
@@ -330,6 +371,10 @@ type Certificate struct {
DNSNames []string
EmailAddresses []string
+ // Name constraints
+ PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
+ PermittedDNSDomains []string
+
PolicyIdentifiers []asn1.ObjectIdentifier
}
@@ -374,12 +419,12 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
// TODO(agl): don't ignore the path length constraint.
var h hash.Hash
- var hashType rsa.PKCS1v15Hash
+ var hashType crypto.Hash
switch c.SignatureAlgorithm {
case SHA1WithRSA:
h = sha1.New()
- hashType = rsa.HashSHA1
+ hashType = crypto.SHA1
default:
return UnsupportedAlgorithmError{}
}
@@ -474,6 +519,18 @@ type policyInformation struct {
// policyQualifiers omitted
}
+// RFC 5280, 4.2.1.10
+type nameConstraints struct {
+ Permitted []generalSubtree "optional,tag:0"
+ Excluded []generalSubtree "optional,tag:1"
+}
+
+type generalSubtree struct {
+ Name string "tag:2,optional,ia5"
+ Min int "optional,tag:0"
+ Max int "optional,tag:1"
+}
+
func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.Error) {
switch algo {
case RSA:
@@ -602,6 +659,43 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
// If we didn't parse any of the names then we
// fall through to the critical check below.
+ case 30:
+ // RFC 5280, 4.2.1.10
+
+ // NameConstraints ::= SEQUENCE {
+ // permittedSubtrees [0] GeneralSubtrees OPTIONAL,
+ // excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+ //
+ // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+ //
+ // GeneralSubtree ::= SEQUENCE {
+ // base GeneralName,
+ // minimum [0] BaseDistance DEFAULT 0,
+ // maximum [1] BaseDistance OPTIONAL }
+ //
+ // BaseDistance ::= INTEGER (0..MAX)
+
+ var constraints nameConstraints
+ _, err := asn1.Unmarshal(e.Value, &constraints)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(constraints.Excluded) > 0 && e.Critical {
+ return out, UnhandledCriticalExtension{}
+ }
+
+ for _, subtree := range constraints.Permitted {
+ if subtree.Min > 0 || subtree.Max > 0 || len(subtree.Name) == 0 {
+ if e.Critical {
+ return out, UnhandledCriticalExtension{}
+ }
+ continue
+ }
+ out.PermittedDNSDomains = append(out.PermittedDNSDomains, subtree.Name)
+ }
+ continue
+
case 35:
// RFC 5280, 4.2.1.1
var a authKeyId
@@ -612,6 +706,44 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
out.AuthorityKeyId = a.Id
continue
+ case 37:
+ // RFC 5280, 4.2.1.12. Extended Key Usage
+
+ // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 }
+ //
+ // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ //
+ // KeyPurposeId ::= OBJECT IDENTIFIER
+
+ var keyUsage []asn1.ObjectIdentifier
+ _, err = asn1.Unmarshal(e.Value, &keyUsage)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, u := range keyUsage {
+ switch {
+ case u.Equal(oidExtKeyUsageAny):
+ out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageAny)
+ case u.Equal(oidExtKeyUsageServerAuth):
+ out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageServerAuth)
+ case u.Equal(oidExtKeyUsageClientAuth):
+ out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageClientAuth)
+ case u.Equal(oidExtKeyUsageCodeSigning):
+ out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageCodeSigning)
+ case u.Equal(oidExtKeyUsageEmailProtection):
+ out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageEmailProtection)
+ case u.Equal(oidExtKeyUsageTimeStamping):
+ out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageTimeStamping)
+ case u.Equal(oidExtKeyUsageOCSPSigning):
+ out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageOCSPSigning)
+ default:
+ out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u)
+ }
+ }
+
+ continue
+
case 14:
// RFC 5280, 4.2.1.2
var keyid []byte
@@ -698,10 +830,11 @@ var (
oidExtensionBasicConstraints = []int{2, 5, 29, 19}
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
+ oidExtensionNameConstraints = []int{2, 5, 29, 30}
)
func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
- ret = make([]extension, 6 /* maximum number of elements. */ )
+ ret = make([]extension, 7 /* maximum number of elements. */ )
n := 0
if template.KeyUsage != 0 {
@@ -778,6 +911,22 @@ func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
n++
}
+ if len(template.PermittedDNSDomains) > 0 {
+ ret[n].Id = oidExtensionNameConstraints
+ ret[n].Critical = template.PermittedDNSDomainsCritical
+
+ var out nameConstraints
+ out.Permitted = make([]generalSubtree, len(template.PermittedDNSDomains))
+ for i, permitted := range template.PermittedDNSDomains {
+ out.Permitted[i] = generalSubtree{Name: permitted}
+ }
+ ret[n].Value, err = asn1.Marshal(out)
+ if err != nil {
+ return
+ }
+ n++
+ }
+
// Adding another extension here? Remember to update the maximum number
// of elements in the make() at the top of the function.
@@ -792,7 +941,8 @@ var (
// CreateSelfSignedCertificate creates a new certificate based on
// a template. The following members of template are used: SerialNumber,
// Subject, NotBefore, NotAfter, KeyUsage, BasicConstraintsValid, IsCA,
-// MaxPathLen, SubjectKeyId, DNSNames.
+// MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
+// PermittedDNSDomains.
//
// The certificate is signed by parent. If parent is equal to template then the
// certificate is self-signed. The parameter pub is the public key of the
@@ -840,7 +990,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
h.Write(tbsCertContents)
digest := h.Sum()
- signature, err := rsa.SignPKCS1v15(rand, priv, rsa.HashSHA1, digest)
+ signature, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, digest)
if err != nil {
return
}