Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package ssh | 5 package ssh |
6 | 6 |
7 // References | 7 // References |
8 // [PROTOCOL.certkeys]: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ PROTOCOL.certkeys | 8 // [PROTOCOL.certkeys]: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ PROTOCOL.certkeys |
9 | 9 |
10 import ( | 10 import ( |
11 "crypto/dsa" | 11 "crypto/dsa" |
12 "crypto/ecdsa" | |
12 "crypto/rsa" | 13 "crypto/rsa" |
13 "time" | 14 "time" |
14 ) | 15 ) |
15 | 16 |
16 // String constants in [PROTOCOL.certkeys] for certificate algorithm names. | 17 // String constants in [PROTOCOL.certkeys] for certificate algorithm names. |
17 const ( | 18 const ( |
18 » hostAlgoRSACertV01 = "ssh-rsa-cert-v01@openssh.com" | 19 » certAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" |
19 » hostAlgoDSACertV01 = "ssh-dss-cert-v01@openssh.com" | 20 » certAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" |
20 » hostAlgoECDSA256CertV01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" | 21 » certAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" |
21 » hostAlgoECDSA384CertV01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" | 22 » certAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" |
22 » hostAlgoECDSA521CertV01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" | 23 » certAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" |
23 ) | 24 ) |
24 | 25 |
25 // Certificate types are used to specify whether a certificate is for identifica tion | 26 // Certificate types are used to specify whether a certificate is for identifica tion |
26 // of a user or a host. Current identities are defined in [PROTOCOL.certkeys]. | 27 // of a user or a host. Current identities are defined in [PROTOCOL.certkeys]. |
27 const ( | 28 const ( |
28 UserCert = 1 | 29 UserCert = 1 |
29 HostCert = 2 | 30 HostCert = 2 |
30 ) | 31 ) |
31 | 32 |
32 type signature struct { | 33 type signature struct { |
33 Format string | 34 Format string |
34 Blob []byte | 35 Blob []byte |
35 } | 36 } |
36 | 37 |
37 type tuple struct { | 38 type tuple struct { |
38 Name string | 39 Name string |
39 Data string | 40 Data string |
40 } | 41 } |
41 | 42 |
42 // An OpenSSHCertV01 represents an OpenSSH certificate as defined in | 43 // An OpenSSHCertV01 represents an OpenSSH certificate as defined in |
43 // [PROTOCOL.certkeys] rev 1.8. Supported formats include | 44 // [PROTOCOL.certkeys] rev 1.8. Supported formats include |
44 // ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com. | 45 // ssh-rsa-cert-v01@openssh.com, ssh-dss-cert-v01@openssh.com, |
46 // ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openss h.com, | |
47 // and ecdsa-sha2-nistp521-cert-v01@openssh.com. | |
dfc
2012/12/13 11:16:03
Suggestion: Maybe the constants above should be ex
jmpittman
2012/12/13 18:38:49
Will do in a follow up CL.
| |
45 type OpenSSHCertV01 struct { | 48 type OpenSSHCertV01 struct { |
46 Nonce []byte | 49 Nonce []byte |
47 » Key interface{} // rsa or dsa *PublicKey | 50 » Key interface{} // rsa, dsa, or ecdsa *PublicKey |
48 Serial uint64 | 51 Serial uint64 |
49 Type uint32 | 52 Type uint32 |
50 KeyId string | 53 KeyId string |
51 ValidPrincipals []string | 54 ValidPrincipals []string |
52 ValidAfter, ValidBefore time.Time | 55 ValidAfter, ValidBefore time.Time |
53 CriticalOptions []tuple | 56 CriticalOptions []tuple |
54 Extensions []tuple | 57 Extensions []tuple |
55 Reserved []byte | 58 Reserved []byte |
56 SignatureKey interface{} // rsa, dsa, or ecdsa *PublicKey | 59 SignatureKey interface{} // rsa, dsa, or ecdsa *PublicKey |
57 Signature *signature | 60 Signature *signature |
58 } | 61 } |
59 | 62 |
60 func parseOpenSSHCertV01(in []byte, algo string) (out *OpenSSHCertV01, rest []by te, ok bool) { | 63 func parseOpenSSHCertV01(in []byte, algo string) (out *OpenSSHCertV01, rest []by te, ok bool) { |
61 cert := new(OpenSSHCertV01) | 64 cert := new(OpenSSHCertV01) |
62 | 65 |
63 if cert.Nonce, in, ok = parseString(in); !ok { | 66 if cert.Nonce, in, ok = parseString(in); !ok { |
64 return | 67 return |
65 } | 68 } |
66 | 69 |
67 switch algo { | 70 switch algo { |
68 » case hostAlgoRSACertV01: | 71 » case certAlgoRSAv01: |
69 var rsaPubKey *rsa.PublicKey | 72 var rsaPubKey *rsa.PublicKey |
70 if rsaPubKey, in, ok = parseRSA(in); !ok { | 73 if rsaPubKey, in, ok = parseRSA(in); !ok { |
71 return | 74 return |
72 } | 75 } |
73 cert.Key = rsaPubKey | 76 cert.Key = rsaPubKey |
74 » case hostAlgoDSACertV01: | 77 » case certAlgoDSAv01: |
75 var dsaPubKey *dsa.PublicKey | 78 var dsaPubKey *dsa.PublicKey |
76 if dsaPubKey, in, ok = parseDSA(in); !ok { | 79 if dsaPubKey, in, ok = parseDSA(in); !ok { |
77 return | 80 return |
78 } | 81 } |
79 cert.Key = dsaPubKey | 82 cert.Key = dsaPubKey |
83 case certAlgoECDSA256v01, certAlgoECDSA384v01, certAlgoECDSA521v01: | |
84 var ecdsaPubKey *ecdsa.PublicKey | |
85 if ecdsaPubKey, in, ok = parseECDSA(in); !ok { | |
86 return | |
87 } | |
88 cert.Key = ecdsaPubKey | |
80 default: | 89 default: |
81 ok = false | 90 ok = false |
82 return | 91 return |
83 } | 92 } |
84 | 93 |
85 if cert.Serial, in, ok = parseUint64(in); !ok { | 94 if cert.Serial, in, ok = parseUint64(in); !ok { |
86 return | 95 return |
87 } | 96 } |
88 | 97 |
89 if cert.Type, in, ok = parseUint32(in); !ok || cert.Type != UserCert && cert.Type != HostCert { | 98 if cert.Type, in, ok = parseUint32(in); !ok || cert.Type != UserCert && cert.Type != HostCert { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
142 | 151 |
143 func marshalOpenSSHCertV01(cert *OpenSSHCertV01) []byte { | 152 func marshalOpenSSHCertV01(cert *OpenSSHCertV01) []byte { |
144 var pubKey []byte | 153 var pubKey []byte |
145 switch cert.Key.(type) { | 154 switch cert.Key.(type) { |
146 case *rsa.PublicKey: | 155 case *rsa.PublicKey: |
147 k := cert.Key.(*rsa.PublicKey) | 156 k := cert.Key.(*rsa.PublicKey) |
148 pubKey = marshalPubRSA(k) | 157 pubKey = marshalPubRSA(k) |
149 case *dsa.PublicKey: | 158 case *dsa.PublicKey: |
150 k := cert.Key.(*dsa.PublicKey) | 159 k := cert.Key.(*dsa.PublicKey) |
151 pubKey = marshalPubDSA(k) | 160 pubKey = marshalPubDSA(k) |
161 case *ecdsa.PublicKey: | |
162 k := cert.Key.(*ecdsa.PublicKey) | |
163 pubKey = marshalPubECDSA(k) | |
152 default: | 164 default: |
153 panic("ssh: unknown public key type in cert") | 165 panic("ssh: unknown public key type in cert") |
154 } | 166 } |
155 | 167 |
156 sigKey := serializePublickey(cert.SignatureKey) | 168 sigKey := serializePublickey(cert.SignatureKey) |
157 | 169 |
158 length := stringLength(len(cert.Nonce)) | 170 length := stringLength(len(cert.Nonce)) |
159 length += len(pubKey) | 171 length += len(pubKey) |
160 length += 8 // Length of Serial | 172 length += 8 // Length of Serial |
161 length += 4 // Length of Type | 173 length += 4 // Length of Type |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
296 return | 308 return |
297 } | 309 } |
298 sig.Format = string(format) | 310 sig.Format = string(format) |
299 | 311 |
300 if sig.Blob, sigBytes, ok = parseString(sigBytes); !ok { | 312 if sig.Blob, sigBytes, ok = parseString(sigBytes); !ok { |
301 return | 313 return |
302 } | 314 } |
303 | 315 |
304 return sig, rest, ok | 316 return sig, rest, ok |
305 } | 317 } |
OLD | NEW |