Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(716)

Side by Side Diff: ssh/certs.go

Issue 14540051: code review 14540051: go.crypto/ssh: Add certificate verification, step up su... (Closed)
Patch Set: diff -r 5ff5636e18c9 https://code.google.com/p/go.crypto Created 10 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ssh/certs_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | ssh/certs_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b