certs.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. // Copyright 2012 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ssh
  5. import (
  6. "time"
  7. )
  8. // These constants from [PROTOCOL.certkeys] represent the algorithm names
  9. // for certificate types supported by this package.
  10. const (
  11. CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
  12. CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
  13. CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
  14. CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
  15. CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
  16. )
  17. // Certificate types are used to specify whether a certificate is for identification
  18. // of a user or a host. Current identities are defined in [PROTOCOL.certkeys].
  19. const (
  20. UserCert = 1
  21. HostCert = 2
  22. )
  23. type signature struct {
  24. Format string
  25. Blob []byte
  26. }
  27. type tuple struct {
  28. Name string
  29. Data string
  30. }
  31. // An OpenSSHCertV01 represents an OpenSSH certificate as defined in
  32. // [PROTOCOL.certkeys]?rev=1.8.
  33. type OpenSSHCertV01 struct {
  34. Nonce []byte
  35. Key PublicKey
  36. Serial uint64
  37. Type uint32
  38. KeyId string
  39. ValidPrincipals []string
  40. ValidAfter, ValidBefore time.Time
  41. CriticalOptions []tuple
  42. Extensions []tuple
  43. Reserved []byte
  44. SignatureKey PublicKey
  45. Signature *signature
  46. }
  47. // validateOpenSSHCertV01Signature uses the cert's SignatureKey to verify that
  48. // the cert's Signature.Blob is the result of signing the cert bytes starting
  49. // from the algorithm string and going up to and including the SignatureKey.
  50. func validateOpenSSHCertV01Signature(cert *OpenSSHCertV01) bool {
  51. return cert.SignatureKey.Verify(cert.BytesForSigning(), cert.Signature.Blob)
  52. }
  53. var certAlgoNames = map[string]string{
  54. KeyAlgoRSA: CertAlgoRSAv01,
  55. KeyAlgoDSA: CertAlgoDSAv01,
  56. KeyAlgoECDSA256: CertAlgoECDSA256v01,
  57. KeyAlgoECDSA384: CertAlgoECDSA384v01,
  58. KeyAlgoECDSA521: CertAlgoECDSA521v01,
  59. }
  60. // certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
  61. // Panics if a non-certificate algorithm is passed.
  62. func certToPrivAlgo(algo string) string {
  63. for privAlgo, pubAlgo := range certAlgoNames {
  64. if pubAlgo == algo {
  65. return privAlgo
  66. }
  67. }
  68. panic("unknown cert algorithm")
  69. }
  70. func (cert *OpenSSHCertV01) marshal(includeAlgo, includeSig bool) []byte {
  71. algoName := cert.PublicKeyAlgo()
  72. pubKey := cert.Key.Marshal()
  73. sigKey := MarshalPublicKey(cert.SignatureKey)
  74. var length int
  75. if includeAlgo {
  76. length += stringLength(len(algoName))
  77. }
  78. length += stringLength(len(cert.Nonce))
  79. length += len(pubKey)
  80. length += 8 // Length of Serial
  81. length += 4 // Length of Type
  82. length += stringLength(len(cert.KeyId))
  83. length += lengthPrefixedNameListLength(cert.ValidPrincipals)
  84. length += 8 // Length of ValidAfter
  85. length += 8 // Length of ValidBefore
  86. length += tupleListLength(cert.CriticalOptions)
  87. length += tupleListLength(cert.Extensions)
  88. length += stringLength(len(cert.Reserved))
  89. length += stringLength(len(sigKey))
  90. if includeSig {
  91. length += signatureLength(cert.Signature)
  92. }
  93. ret := make([]byte, length)
  94. r := ret
  95. if includeAlgo {
  96. r = marshalString(r, []byte(algoName))
  97. }
  98. r = marshalString(r, cert.Nonce)
  99. copy(r, pubKey)
  100. r = r[len(pubKey):]
  101. r = marshalUint64(r, cert.Serial)
  102. r = marshalUint32(r, cert.Type)
  103. r = marshalString(r, []byte(cert.KeyId))
  104. r = marshalLengthPrefixedNameList(r, cert.ValidPrincipals)
  105. r = marshalUint64(r, uint64(cert.ValidAfter.Unix()))
  106. r = marshalUint64(r, uint64(cert.ValidBefore.Unix()))
  107. r = marshalTupleList(r, cert.CriticalOptions)
  108. r = marshalTupleList(r, cert.Extensions)
  109. r = marshalString(r, cert.Reserved)
  110. r = marshalString(r, sigKey)
  111. if includeSig {
  112. r = marshalSignature(r, cert.Signature)
  113. }
  114. if len(r) > 0 {
  115. panic("ssh: internal error, marshaling certificate did not fill the entire buffer")
  116. }
  117. return ret
  118. }
  119. func (cert *OpenSSHCertV01) BytesForSigning() []byte {
  120. return cert.marshal(true, false)
  121. }
  122. func (cert *OpenSSHCertV01) Marshal() []byte {
  123. return cert.marshal(false, true)
  124. }
  125. func (c *OpenSSHCertV01) PublicKeyAlgo() string {
  126. algo, ok := certAlgoNames[c.Key.PublicKeyAlgo()]
  127. if !ok {
  128. panic("unknown cert key type")
  129. }
  130. return algo
  131. }
  132. func (c *OpenSSHCertV01) PrivateKeyAlgo() string {
  133. return c.Key.PrivateKeyAlgo()
  134. }
  135. func (c *OpenSSHCertV01) Verify(data []byte, sig []byte) bool {
  136. return c.Key.Verify(data, sig)
  137. }
  138. func parseOpenSSHCertV01(in []byte, algo string) (out *OpenSSHCertV01, rest []byte, ok bool) {
  139. cert := new(OpenSSHCertV01)
  140. if cert.Nonce, in, ok = parseString(in); !ok {
  141. return
  142. }
  143. privAlgo := certToPrivAlgo(algo)
  144. cert.Key, in, ok = parsePubKey(in, privAlgo)
  145. if !ok {
  146. return
  147. }
  148. // We test PublicKeyAlgo to make sure we don't use some weird sub-cert.
  149. if cert.Key.PublicKeyAlgo() != privAlgo {
  150. ok = false
  151. return
  152. }
  153. if cert.Serial, in, ok = parseUint64(in); !ok {
  154. return
  155. }
  156. if cert.Type, in, ok = parseUint32(in); !ok {
  157. return
  158. }
  159. keyId, in, ok := parseString(in)
  160. if !ok {
  161. return
  162. }
  163. cert.KeyId = string(keyId)
  164. if cert.ValidPrincipals, in, ok = parseLengthPrefixedNameList(in); !ok {
  165. return
  166. }
  167. va, in, ok := parseUint64(in)
  168. if !ok {
  169. return
  170. }
  171. cert.ValidAfter = time.Unix(int64(va), 0)
  172. vb, in, ok := parseUint64(in)
  173. if !ok {
  174. return
  175. }
  176. cert.ValidBefore = time.Unix(int64(vb), 0)
  177. if cert.CriticalOptions, in, ok = parseTupleList(in); !ok {
  178. return
  179. }
  180. if cert.Extensions, in, ok = parseTupleList(in); !ok {
  181. return
  182. }
  183. if cert.Reserved, in, ok = parseString(in); !ok {
  184. return
  185. }
  186. sigKey, in, ok := parseString(in)
  187. if !ok {
  188. return
  189. }
  190. if cert.SignatureKey, _, ok = ParsePublicKey(sigKey); !ok {
  191. return
  192. }
  193. if cert.Signature, in, ok = parseSignature(in); !ok {
  194. return
  195. }
  196. ok = true
  197. return cert, in, ok
  198. }
  199. func lengthPrefixedNameListLength(namelist []string) int {
  200. length := 4 // length prefix for list
  201. for _, name := range namelist {
  202. length += 4 // length prefix for name
  203. length += len(name)
  204. }
  205. return length
  206. }
  207. func marshalLengthPrefixedNameList(to []byte, namelist []string) []byte {
  208. length := uint32(lengthPrefixedNameListLength(namelist) - 4)
  209. to = marshalUint32(to, length)
  210. for _, name := range namelist {
  211. to = marshalString(to, []byte(name))
  212. }
  213. return to
  214. }
  215. func parseLengthPrefixedNameList(in []byte) (out []string, rest []byte, ok bool) {
  216. list, rest, ok := parseString(in)
  217. if !ok {
  218. return
  219. }
  220. for len(list) > 0 {
  221. var next []byte
  222. if next, list, ok = parseString(list); !ok {
  223. return nil, nil, false
  224. }
  225. out = append(out, string(next))
  226. }
  227. ok = true
  228. return
  229. }
  230. func tupleListLength(tupleList []tuple) int {
  231. length := 4 // length prefix for list
  232. for _, t := range tupleList {
  233. length += 4 // length prefix for t.Name
  234. length += len(t.Name)
  235. length += 4 // length prefix for t.Data
  236. length += len(t.Data)
  237. }
  238. return length
  239. }
  240. func marshalTupleList(to []byte, tuplelist []tuple) []byte {
  241. length := uint32(tupleListLength(tuplelist) - 4)
  242. to = marshalUint32(to, length)
  243. for _, t := range tuplelist {
  244. to = marshalString(to, []byte(t.Name))
  245. to = marshalString(to, []byte(t.Data))
  246. }
  247. return to
  248. }
  249. func parseTupleList(in []byte) (out []tuple, rest []byte, ok bool) {
  250. list, rest, ok := parseString(in)
  251. if !ok {
  252. return
  253. }
  254. for len(list) > 0 {
  255. var name, data []byte
  256. var ok bool
  257. name, list, ok = parseString(list)
  258. if !ok {
  259. return nil, nil, false
  260. }
  261. data, list, ok = parseString(list)
  262. if !ok {
  263. return nil, nil, false
  264. }
  265. out = append(out, tuple{string(name), string(data)})
  266. }
  267. ok = true
  268. return
  269. }
  270. func signatureLength(sig *signature) int {
  271. length := 4 // length prefix for signature
  272. length += stringLength(len(sig.Format))
  273. length += stringLength(len(sig.Blob))
  274. return length
  275. }
  276. func marshalSignature(to []byte, sig *signature) []byte {
  277. length := uint32(signatureLength(sig) - 4)
  278. to = marshalUint32(to, length)
  279. to = marshalString(to, []byte(sig.Format))
  280. to = marshalString(to, sig.Blob)
  281. return to
  282. }
  283. func parseSignatureBody(in []byte) (out *signature, rest []byte, ok bool) {
  284. var format []byte
  285. if format, in, ok = parseString(in); !ok {
  286. return
  287. }
  288. out = &signature{
  289. Format: string(format),
  290. }
  291. if out.Blob, in, ok = parseString(in); !ok {
  292. return
  293. }
  294. return out, in, ok
  295. }
  296. func parseSignature(in []byte) (out *signature, rest []byte, ok bool) {
  297. var sigBytes []byte
  298. if sigBytes, rest, ok = parseString(in); !ok {
  299. return
  300. }
  301. out, sigBytes, ok = parseSignatureBody(sigBytes)
  302. if !ok || len(sigBytes) > 0 {
  303. return nil, nil, false
  304. }
  305. return
  306. }