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

Delta Between Two Patch Sets: ssh/certs.go

Issue 14540051: code review 14540051: go.crypto/ssh: Add certificate verification, step up su... (Closed)
Left Patch Set: diff -r 812c06b5a384 https://code.google.com/p/go.crypto Created 10 years, 5 months ago
Right 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:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | ssh/certs_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 // 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
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 }
LEFTRIGHT
« no previous file | ssh/certs_test.go » ('j') | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

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