certs.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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. // References
  6. // [PROTOCOL.certkeys]: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys
  7. import (
  8. "crypto/dsa"
  9. "crypto/rsa"
  10. "time"
  11. )
  12. // String constants in [PROTOCOL.certkeys] for certificate algorithm names.
  13. const (
  14. hostAlgoRSACertV01 = "ssh-rsa-cert-v01@openssh.com"
  15. hostAlgoDSACertV01 = "ssh-dss-cert-v01@openssh.com"
  16. hostAlgoECDSA256CertV01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
  17. hostAlgoECDSA384CertV01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
  18. hostAlgoECDSA521CertV01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
  19. )
  20. // Certificate types are used to specify whether a certificate is for identification
  21. // of a user or a host. Current identities are defined in [PROTOCOL.certkeys].
  22. const (
  23. UserCert = 1
  24. HostCert = 2
  25. )
  26. type signature struct {
  27. Format string
  28. Blob []byte
  29. }
  30. type tuple struct {
  31. Name string
  32. Data string
  33. }
  34. // An OpenSSHCertV01 represents an OpenSSH certificate as defined in
  35. // [PROTOCOL.certkeys] rev 1.8. Supported formats include
  36. // ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com.
  37. type OpenSSHCertV01 struct {
  38. Nonce []byte
  39. Key interface{} // rsa or dsa *PublicKey
  40. Serial uint64
  41. Type uint32
  42. KeyId string
  43. ValidPrincipals []string
  44. ValidAfter, ValidBefore time.Time
  45. CriticalOptions []tuple
  46. Extensions []tuple
  47. Reserved []byte
  48. SignatureKey interface{} // rsa, dsa, or ecdsa *PublicKey
  49. Signature *signature
  50. }
  51. func parseOpenSSHCertV01(in []byte, algo string) (out *OpenSSHCertV01, rest []byte, ok bool) {
  52. cert := new(OpenSSHCertV01)
  53. if cert.Nonce, in, ok = parseString(in); !ok {
  54. return
  55. }
  56. switch algo {
  57. case hostAlgoRSACertV01:
  58. var rsaPubKey *rsa.PublicKey
  59. if rsaPubKey, in, ok = parseRSA(in); !ok {
  60. return
  61. }
  62. cert.Key = rsaPubKey
  63. case hostAlgoDSACertV01:
  64. var dsaPubKey *dsa.PublicKey
  65. if dsaPubKey, in, ok = parseDSA(in); !ok {
  66. return
  67. }
  68. cert.Key = dsaPubKey
  69. default:
  70. return
  71. }
  72. if cert.Serial, in, ok = parseUint64(in); !ok {
  73. return
  74. }
  75. if cert.Type, in, ok = parseUint32(in); !ok || cert.Type != UserCert && cert.Type != HostCert {
  76. return
  77. }
  78. keyId, in, ok := parseString(in)
  79. if !ok {
  80. return
  81. }
  82. cert.KeyId = string(keyId)
  83. if cert.ValidPrincipals, in, ok = parseLengthPrefixedNameList(in); !ok {
  84. return
  85. }
  86. va, in, ok := parseUint64(in)
  87. if !ok {
  88. return
  89. }
  90. cert.ValidAfter = time.Unix(int64(va), 0)
  91. vb, in, ok := parseUint64(in)
  92. if !ok {
  93. return
  94. }
  95. cert.ValidBefore = time.Unix(int64(vb), 0)
  96. if cert.CriticalOptions, in, ok = parseTupleList(in); !ok {
  97. return
  98. }
  99. if cert.Extensions, in, ok = parseTupleList(in); !ok {
  100. return
  101. }
  102. if cert.Reserved, in, ok = parseString(in); !ok {
  103. return
  104. }
  105. sigKey, in, ok := parseString(in)
  106. if !ok {
  107. return
  108. }
  109. if cert.SignatureKey, _, ok = parsePubKey(sigKey); !ok {
  110. return
  111. }
  112. if cert.Signature, in, ok = parseSignature(in); !ok {
  113. return
  114. }
  115. ok = true
  116. return cert, in, ok
  117. }
  118. func marshalOpenSSHCertV01(cert *OpenSSHCertV01) []byte {
  119. var pubKey []byte
  120. switch cert.Key.(type) {
  121. case *rsa.PublicKey:
  122. k := cert.Key.(*rsa.PublicKey)
  123. pubKey = marshalPubRSA(k)
  124. case *dsa.PublicKey:
  125. k := cert.Key.(*dsa.PublicKey)
  126. pubKey = marshalPubDSA(k)
  127. default:
  128. panic("ssh: unknown public key type in cert")
  129. }
  130. sigKey := serializePublickey(cert.SignatureKey)
  131. length := stringLength(len(cert.Nonce))
  132. length += len(pubKey)
  133. length += 8 // Length of Serial
  134. length += 4 // Length of Type
  135. length += stringLength(len(cert.KeyId))
  136. length += lengthPrefixedNameListLength(cert.ValidPrincipals)
  137. length += 8 // Length of ValidAfter
  138. length += 8 // Length of ValidBefore
  139. length += tupleListLength(cert.CriticalOptions)
  140. length += tupleListLength(cert.Extensions)
  141. length += stringLength(len(cert.Reserved))
  142. length += stringLength(len(sigKey))
  143. length += signatureLength(cert.Signature)
  144. ret := make([]byte, length)
  145. r := marshalString(ret, cert.Nonce)
  146. copy(r, pubKey)
  147. r = r[len(pubKey):]
  148. r = marshalUint64(r, cert.Serial)
  149. r = marshalUint32(r, cert.Type)
  150. r = marshalString(r, []byte(cert.KeyId))
  151. r = marshalLengthPrefixedNameList(r, cert.ValidPrincipals)
  152. r = marshalUint64(r, uint64(cert.ValidAfter.Unix()))
  153. r = marshalUint64(r, uint64(cert.ValidBefore.Unix()))
  154. r = marshalTupleList(r, cert.CriticalOptions)
  155. r = marshalTupleList(r, cert.Extensions)
  156. r = marshalString(r, cert.Reserved)
  157. r = marshalString(r, sigKey)
  158. r = marshalSignature(r, cert.Signature)
  159. if len(r) > 0 {
  160. panic("internal error")
  161. }
  162. return ret
  163. }
  164. func lengthPrefixedNameListLength(namelist []string) int {
  165. length := 4 // length prefix for list
  166. for _, name := range namelist {
  167. length += 4 // length prefix for name
  168. length += len(name)
  169. }
  170. return length
  171. }
  172. func marshalLengthPrefixedNameList(to []byte, namelist []string) []byte {
  173. length := uint32(lengthPrefixedNameListLength(namelist) - 4)
  174. to = marshalUint32(to, length)
  175. for _, name := range namelist {
  176. to = marshalString(to, []byte(name))
  177. }
  178. return to
  179. }
  180. func parseLengthPrefixedNameList(in []byte) (out []string, rest []byte, ok bool) {
  181. list, rest, ok := parseString(in)
  182. if !ok {
  183. return
  184. }
  185. for len(list) > 0 {
  186. var next []byte
  187. if next, list, ok = parseString(list); !ok {
  188. return nil, nil, false
  189. }
  190. out = append(out, string(next))
  191. }
  192. ok = true
  193. return
  194. }
  195. func tupleListLength(tupleList []tuple) int {
  196. length := 4 // length prefix for list
  197. for _, t := range tupleList {
  198. length += 4 // length prefix for t.Name
  199. length += len(t.Name)
  200. length += 4 // length prefix for t.Data
  201. length += len(t.Data)
  202. }
  203. return length
  204. }
  205. func marshalTupleList(to []byte, tuplelist []tuple) []byte {
  206. length := uint32(tupleListLength(tuplelist) - 4)
  207. to = marshalUint32(to, length)
  208. for _, t := range tuplelist {
  209. to = marshalString(to, []byte(t.Name))
  210. to = marshalString(to, []byte(t.Data))
  211. }
  212. return to
  213. }
  214. func parseTupleList(in []byte) (out []tuple, rest []byte, ok bool) {
  215. list, rest, ok := parseString(in)
  216. if !ok {
  217. return
  218. }
  219. for len(list) > 0 {
  220. var name, data []byte
  221. var ok bool
  222. name, list, ok = parseString(list)
  223. if !ok {
  224. return nil, nil, false
  225. }
  226. data, list, ok = parseString(list)
  227. if !ok {
  228. return nil, nil, false
  229. }
  230. out = append(out, tuple{string(name), string(data)})
  231. }
  232. ok = true
  233. return
  234. }
  235. func signatureLength(sig *signature) int {
  236. length := 4 // length prefix for signature
  237. length += stringLength(len(sig.Format))
  238. length += stringLength(len(sig.Blob))
  239. return length
  240. }
  241. func marshalSignature(to []byte, sig *signature) []byte {
  242. length := uint32(signatureLength(sig) - 4)
  243. to = marshalUint32(to, length)
  244. to = marshalString(to, []byte(sig.Format))
  245. to = marshalString(to, sig.Blob)
  246. return to
  247. }
  248. func parseSignature(in []byte) (out *signature, rest []byte, ok bool) {
  249. var sigBytes, format []byte
  250. sig := new(signature)
  251. if sigBytes, rest, ok = parseString(in); !ok {
  252. return
  253. }
  254. if format, sigBytes, ok = parseString(sigBytes); !ok {
  255. return
  256. }
  257. sig.Format = string(format)
  258. if sig.Blob, sigBytes, ok = parseString(sigBytes); !ok {
  259. return
  260. }
  261. return sig, rest, ok
  262. }