certs.go 7.6 KB

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