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 import ( | 7 import ( |
8 "time" | 8 "time" |
9 ) | 9 ) |
10 | 10 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 KeyId string | 45 KeyId string |
46 ValidPrincipals []string | 46 ValidPrincipals []string |
47 ValidAfter, ValidBefore time.Time | 47 ValidAfter, ValidBefore time.Time |
48 CriticalOptions []tuple | 48 CriticalOptions []tuple |
49 Extensions []tuple | 49 Extensions []tuple |
50 Reserved []byte | 50 Reserved []byte |
51 SignatureKey PublicKey | 51 SignatureKey PublicKey |
52 Signature *signature | 52 Signature *signature |
53 } | 53 } |
54 | 54 |
| 55 // validateOpenSSHCertV01Signature uses the cert's SignatureKey to verify that |
| 56 // the cert's Signature.Blob is the result of signing the cert bytes starting |
| 57 // from the algorithm string and going up to and including the SignatureKey. |
| 58 func validateOpenSSHCertV01Signature(cert *OpenSSHCertV01) bool { |
| 59 return cert.SignatureKey.Verify(cert.BytesForSigning(), cert.Signature.B
lob) |
| 60 } |
| 61 |
55 var certAlgoNames = map[string]string{ | 62 var certAlgoNames = map[string]string{ |
56 KeyAlgoRSA: CertAlgoRSAv01, | 63 KeyAlgoRSA: CertAlgoRSAv01, |
57 KeyAlgoDSA: CertAlgoDSAv01, | 64 KeyAlgoDSA: CertAlgoDSAv01, |
58 KeyAlgoECDSA256: CertAlgoECDSA256v01, | 65 KeyAlgoECDSA256: CertAlgoECDSA256v01, |
59 KeyAlgoECDSA384: CertAlgoECDSA384v01, | 66 KeyAlgoECDSA384: CertAlgoECDSA384v01, |
60 KeyAlgoECDSA521: CertAlgoECDSA521v01, | 67 KeyAlgoECDSA521: CertAlgoECDSA521v01, |
61 } | 68 } |
62 | 69 |
63 // certToPrivAlgo returns the underlying algorithm for a certificate algorithm. | 70 // certToPrivAlgo returns the underlying algorithm for a certificate algorithm. |
64 // Panics if a non-certificate algorithm is passed. | 71 // Panics if a non-certificate algorithm is passed. |
65 func certToPrivAlgo(algo string) string { | 72 func certToPrivAlgo(algo string) string { |
66 for privAlgo, pubAlgo := range certAlgoNames { | 73 for privAlgo, pubAlgo := range certAlgoNames { |
67 if pubAlgo == algo { | 74 if pubAlgo == algo { |
68 return privAlgo | 75 return privAlgo |
69 } | 76 } |
70 } | 77 } |
71 panic("unknown cert algorithm") | 78 panic("unknown cert algorithm") |
72 } | 79 } |
73 | 80 |
| 81 func (cert *OpenSSHCertV01) marshal(includeAlgo, includeSig bool) []byte { |
| 82 algoName := cert.PublicKeyAlgo() |
| 83 pubKey := cert.Key.Marshal() |
| 84 sigKey := MarshalPublicKey(cert.SignatureKey) |
| 85 |
| 86 var length int |
| 87 if includeAlgo { |
| 88 length += stringLength(len(algoName)) |
| 89 } |
| 90 length += stringLength(len(cert.Nonce)) |
| 91 length += len(pubKey) |
| 92 length += 8 // Length of Serial |
| 93 length += 4 // Length of Type |
| 94 length += stringLength(len(cert.KeyId)) |
| 95 length += lengthPrefixedNameListLength(cert.ValidPrincipals) |
| 96 length += 8 // Length of ValidAfter |
| 97 length += 8 // Length of ValidBefore |
| 98 length += tupleListLength(cert.CriticalOptions) |
| 99 length += tupleListLength(cert.Extensions) |
| 100 length += stringLength(len(cert.Reserved)) |
| 101 length += stringLength(len(sigKey)) |
| 102 if includeSig { |
| 103 length += signatureLength(cert.Signature) |
| 104 } |
| 105 |
| 106 ret := make([]byte, length) |
| 107 r := ret |
| 108 if includeAlgo { |
| 109 r = marshalString(r, []byte(algoName)) |
| 110 } |
| 111 r = marshalString(r, cert.Nonce) |
| 112 copy(r, pubKey) |
| 113 r = r[len(pubKey):] |
| 114 r = marshalUint64(r, cert.Serial) |
| 115 r = marshalUint32(r, cert.Type) |
| 116 r = marshalString(r, []byte(cert.KeyId)) |
| 117 r = marshalLengthPrefixedNameList(r, cert.ValidPrincipals) |
| 118 r = marshalUint64(r, uint64(cert.ValidAfter.Unix())) |
| 119 r = marshalUint64(r, uint64(cert.ValidBefore.Unix())) |
| 120 r = marshalTupleList(r, cert.CriticalOptions) |
| 121 r = marshalTupleList(r, cert.Extensions) |
| 122 r = marshalString(r, cert.Reserved) |
| 123 r = marshalString(r, sigKey) |
| 124 if includeSig { |
| 125 r = marshalSignature(r, cert.Signature) |
| 126 } |
| 127 if len(r) > 0 { |
| 128 panic("ssh: internal error, marshaling certificate did not fill
the entire buffer") |
| 129 } |
| 130 return ret |
| 131 } |
| 132 |
| 133 func (cert *OpenSSHCertV01) BytesForSigning() []byte { |
| 134 return cert.marshal(true, false) |
| 135 } |
| 136 |
| 137 func (cert *OpenSSHCertV01) Marshal() []byte { |
| 138 return cert.marshal(false, true) |
| 139 } |
| 140 |
74 func (c *OpenSSHCertV01) PublicKeyAlgo() string { | 141 func (c *OpenSSHCertV01) PublicKeyAlgo() string { |
75 algo, ok := certAlgoNames[c.Key.PublicKeyAlgo()] | 142 algo, ok := certAlgoNames[c.Key.PublicKeyAlgo()] |
76 if !ok { | 143 if !ok { |
77 panic("unknown cert key type") | 144 panic("unknown cert key type") |
78 } | 145 } |
79 return algo | 146 return algo |
80 } | 147 } |
81 | 148 |
82 func (c *OpenSSHCertV01) PrivateKeyAlgo() string { | 149 func (c *OpenSSHCertV01) PrivateKeyAlgo() string { |
83 return c.Key.PrivateKeyAlgo() | 150 return c.Key.PrivateKeyAlgo() |
(...skipping 19 matching lines...) Expand all Loading... |
103 // We test PublicKeyAlgo to make sure we don't use some weird sub-cert. | 170 // We test PublicKeyAlgo to make sure we don't use some weird sub-cert. |
104 if cert.Key.PublicKeyAlgo() != privAlgo { | 171 if cert.Key.PublicKeyAlgo() != privAlgo { |
105 ok = false | 172 ok = false |
106 return | 173 return |
107 } | 174 } |
108 | 175 |
109 if cert.Serial, in, ok = parseUint64(in); !ok { | 176 if cert.Serial, in, ok = parseUint64(in); !ok { |
110 return | 177 return |
111 } | 178 } |
112 | 179 |
113 » if cert.Type, in, ok = parseUint32(in); !ok || cert.Type != UserCert &&
cert.Type != HostCert { | 180 » if cert.Type, in, ok = parseUint32(in); !ok { |
114 return | 181 return |
115 } | 182 } |
116 | 183 |
117 keyId, in, ok := parseString(in) | 184 keyId, in, ok := parseString(in) |
118 if !ok { | 185 if !ok { |
119 return | 186 return |
120 } | 187 } |
121 cert.KeyId = string(keyId) | 188 cert.KeyId = string(keyId) |
122 | 189 |
123 if cert.ValidPrincipals, in, ok = parseLengthPrefixedNameList(in); !ok { | 190 if cert.ValidPrincipals, in, ok = parseLengthPrefixedNameList(in); !ok { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 } | 224 } |
158 | 225 |
159 if cert.Signature, in, ok = parseSignature(in); !ok { | 226 if cert.Signature, in, ok = parseSignature(in); !ok { |
160 return | 227 return |
161 } | 228 } |
162 | 229 |
163 ok = true | 230 ok = true |
164 return cert, in, ok | 231 return cert, in, ok |
165 } | 232 } |
166 | 233 |
167 func (cert *OpenSSHCertV01) Marshal() []byte { | |
168 pubKey := cert.Key.Marshal() | |
169 sigKey := MarshalPublicKey(cert.SignatureKey) | |
170 | |
171 length := stringLength(len(cert.Nonce)) | |
172 length += len(pubKey) | |
173 length += 8 // Length of Serial | |
174 length += 4 // Length of Type | |
175 length += stringLength(len(cert.KeyId)) | |
176 length += lengthPrefixedNameListLength(cert.ValidPrincipals) | |
177 length += 8 // Length of ValidAfter | |
178 length += 8 // Length of ValidBefore | |
179 length += tupleListLength(cert.CriticalOptions) | |
180 length += tupleListLength(cert.Extensions) | |
181 length += stringLength(len(cert.Reserved)) | |
182 length += stringLength(len(sigKey)) | |
183 length += signatureLength(cert.Signature) | |
184 | |
185 ret := make([]byte, length) | |
186 r := marshalString(ret, cert.Nonce) | |
187 copy(r, pubKey) | |
188 r = r[len(pubKey):] | |
189 r = marshalUint64(r, cert.Serial) | |
190 r = marshalUint32(r, cert.Type) | |
191 r = marshalString(r, []byte(cert.KeyId)) | |
192 r = marshalLengthPrefixedNameList(r, cert.ValidPrincipals) | |
193 r = marshalUint64(r, uint64(cert.ValidAfter.Unix())) | |
194 r = marshalUint64(r, uint64(cert.ValidBefore.Unix())) | |
195 r = marshalTupleList(r, cert.CriticalOptions) | |
196 r = marshalTupleList(r, cert.Extensions) | |
197 r = marshalString(r, cert.Reserved) | |
198 r = marshalString(r, sigKey) | |
199 r = marshalSignature(r, cert.Signature) | |
200 if len(r) > 0 { | |
201 panic("internal error") | |
202 } | |
203 return ret | |
204 } | |
205 | |
206 func lengthPrefixedNameListLength(namelist []string) int { | 234 func lengthPrefixedNameListLength(namelist []string) int { |
207 length := 4 // length prefix for list | 235 length := 4 // length prefix for list |
208 for _, name := range namelist { | 236 for _, name := range namelist { |
209 length += 4 // length prefix for name | 237 length += 4 // length prefix for name |
210 length += len(name) | 238 length += len(name) |
211 } | 239 } |
212 return length | 240 return length |
213 } | 241 } |
214 | 242 |
215 func marshalLengthPrefixedNameList(to []byte, namelist []string) []byte { | 243 func marshalLengthPrefixedNameList(to []byte, namelist []string) []byte { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 | 341 |
314 return out, in, ok | 342 return out, in, ok |
315 } | 343 } |
316 | 344 |
317 func parseSignature(in []byte) (out *signature, rest []byte, ok bool) { | 345 func parseSignature(in []byte) (out *signature, rest []byte, ok bool) { |
318 var sigBytes []byte | 346 var sigBytes []byte |
319 if sigBytes, rest, ok = parseString(in); !ok { | 347 if sigBytes, rest, ok = parseString(in); !ok { |
320 return | 348 return |
321 } | 349 } |
322 | 350 |
323 » // TODO(hanwen): this is a bug; 'rest' gets swallowed. | 351 » out, sigBytes, ok = parseSignatureBody(sigBytes) |
324 » return parseSignatureBody(sigBytes) | 352 » if !ok || len(sigBytes) > 0 { |
| 353 » » return nil, nil, false |
| 354 » } |
| 355 » return |
325 } | 356 } |
OLD | NEW |