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