auth.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. package ike
  2. import (
  3. "bytes"
  4. "crypto"
  5. "crypto/ecdsa"
  6. "crypto/rsa"
  7. "crypto/sha1"
  8. "crypto/sha256"
  9. "crypto/sha512"
  10. "crypto/subtle"
  11. "crypto/x509"
  12. "crypto/x509/pkix"
  13. "encoding/asn1"
  14. "errors"
  15. "fmt"
  16. "math/big"
  17. "strings"
  18. "vocat/internal/vowifi"
  19. )
  20. const (
  21. authMethodRSASignature = 1
  22. authMethodSharedKeyMIC = 2
  23. authMethodECDSASHA256P256 = 9
  24. authMethodECDSASHA384P384 = 10
  25. authMethodECDSASHA512P521 = 11
  26. authMethodDigitalSignature = 14
  27. )
  28. var (
  29. oidSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
  30. oidSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
  31. oidSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
  32. oidECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
  33. oidECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
  34. oidECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
  35. )
  36. func responderSignedOctets(
  37. initialResponse []byte,
  38. initiatorNonce []byte,
  39. suite negotiatedSuite,
  40. skpr []byte,
  41. idr payload,
  42. ) ([]byte, error) {
  43. idHash, err := prf(suite, skpr, idr.Body)
  44. if err != nil {
  45. return nil, err
  46. }
  47. signed := make([]byte, 0, len(initialResponse)+len(initiatorNonce)+len(idHash))
  48. signed = append(signed, initialResponse...)
  49. signed = append(signed, initiatorNonce...)
  50. signed = append(signed, idHash...)
  51. return signed, nil
  52. }
  53. func initiatorSignedOctets(
  54. initialRequest []byte,
  55. responderNonce []byte,
  56. suite negotiatedSuite,
  57. skpi []byte,
  58. idi payload,
  59. ) ([]byte, error) {
  60. idHash, err := prf(suite, skpi, idi.Body)
  61. if err != nil {
  62. return nil, err
  63. }
  64. signed := make([]byte, 0, len(initialRequest)+len(responderNonce)+len(idHash))
  65. signed = append(signed, initialRequest...)
  66. signed = append(signed, responderNonce...)
  67. signed = append(signed, idHash...)
  68. return signed, nil
  69. }
  70. func makeEAPInitiatorAUTH(
  71. msk []byte,
  72. initialRequest []byte,
  73. responderNonce []byte,
  74. suite negotiatedSuite,
  75. skpi []byte,
  76. idi payload,
  77. ) (payload, error) {
  78. signed, err := initiatorSignedOctets(initialRequest, responderNonce, suite, skpi, idi)
  79. if err != nil {
  80. return payload{}, err
  81. }
  82. paddedKey, err := prf(suite, msk, []byte("Key Pad for IKEv2"))
  83. if err != nil {
  84. return payload{}, err
  85. }
  86. authValue, err := prf(suite, paddedKey, signed)
  87. if err != nil {
  88. return payload{}, err
  89. }
  90. body := make([]byte, 4+len(authValue))
  91. body[0] = authMethodSharedKeyMIC
  92. copy(body[4:], authValue)
  93. return payload{Type: payloadAuth, Body: body}, nil
  94. }
  95. func verifyEAPResponderAUTH(
  96. auth payload,
  97. msk []byte,
  98. initialResponse []byte,
  99. initiatorNonce []byte,
  100. suite negotiatedSuite,
  101. skpr []byte,
  102. idr payload,
  103. ) error {
  104. if len(auth.Body) < 4 || auth.Body[0] != authMethodSharedKeyMIC {
  105. return errors.New("ike: final responder AUTH does not use the EAP shared-key MIC")
  106. }
  107. signed, err := responderSignedOctets(initialResponse, initiatorNonce, suite, skpr, idr)
  108. if err != nil {
  109. return err
  110. }
  111. paddedKey, err := prf(suite, msk, []byte("Key Pad for IKEv2"))
  112. if err != nil {
  113. return err
  114. }
  115. expected, err := prf(suite, paddedKey, signed)
  116. if err != nil {
  117. return err
  118. }
  119. if len(auth.Body[4:]) != len(expected) || subtle.ConstantTimeCompare(auth.Body[4:], expected) != 1 {
  120. return errors.New("ike: final responder AUTH is invalid")
  121. }
  122. return nil
  123. }
  124. func validateInitialResponderAUTH(
  125. payloads []payload,
  126. initialResponse []byte,
  127. initiatorNonce []byte,
  128. suite negotiatedSuite,
  129. skpr []byte,
  130. expectedIDr string,
  131. serverName string,
  132. roots *x509.CertPool,
  133. pinned crypto.PublicKey,
  134. allowMissing bool,
  135. ) (vowifi.ResponderAUTHStatus, payload, error) {
  136. idrPayloads := payloadsOfType(payloads, payloadIDr)
  137. authPayloads := payloadsOfType(payloads, payloadAuth)
  138. if len(authPayloads) == 0 {
  139. if len(idrPayloads) > 1 {
  140. return vowifi.ResponderAUTHInvalid, payload{}, errors.New("ike: duplicate responder identity payload")
  141. }
  142. if allowMissing {
  143. if len(idrPayloads) == 1 {
  144. return vowifi.ResponderAUTHMissing, idrPayloads[0], nil
  145. }
  146. return vowifi.ResponderAUTHMissing, payload{}, nil
  147. }
  148. return vowifi.ResponderAUTHMissing, payload{}, vowifi.ErrResponderAUTHRequired
  149. }
  150. if len(authPayloads) != 1 || len(idrPayloads) != 1 {
  151. return vowifi.ResponderAUTHInvalid, payload{}, errors.New("ike: responder AUTH requires exactly one IDr and AUTH payload")
  152. }
  153. idr := idrPayloads[0]
  154. auth := authPayloads[0]
  155. if len(idr.Body) < 4 || len(auth.Body) < 5 {
  156. return vowifi.ResponderAUTHInvalid, idr, errors.New("ike: responder IDr or AUTH payload is truncated")
  157. }
  158. if err := validateFQDNIDr(idr, expectedIDr, "initial ePDG"); err != nil {
  159. return vowifi.ResponderAUTHInvalid, idr, err
  160. }
  161. publicKey := pinned
  162. if publicKey == nil {
  163. certificates, err := parseResponderCertificates(payloads)
  164. if err != nil {
  165. return vowifi.ResponderAUTHInvalid, idr, err
  166. }
  167. if len(certificates) == 0 {
  168. return vowifi.ResponderAUTHInvalid, idr, errors.New("ike: responder AUTH has no certificate or pinned public key")
  169. }
  170. if err := verifyResponderCertificate(certificates, roots, serverName); err != nil {
  171. return vowifi.ResponderAUTHInvalid, idr, err
  172. }
  173. publicKey = certificates[0].PublicKey
  174. }
  175. signed, err := responderSignedOctets(initialResponse, initiatorNonce, suite, skpr, idr)
  176. if err != nil {
  177. return vowifi.ResponderAUTHInvalid, idr, err
  178. }
  179. if err := verifyDigitalAUTH(publicKey, auth.Body[0], auth.Body[4:], signed); err != nil {
  180. return vowifi.ResponderAUTHInvalid, idr, fmt.Errorf("ike: invalid responder AUTH: %w", err)
  181. }
  182. return vowifi.ResponderAUTHVerified, idr, nil
  183. }
  184. func validateFQDNIDr(idr payload, expectedIDr string, label string) error {
  185. if len(idr.Body) < 4 {
  186. return errors.New("ike: responder identity is truncated")
  187. }
  188. identityType := idr.Body[0]
  189. identity := strings.TrimSpace(string(idr.Body[4:]))
  190. if identityType != 2 {
  191. return fmt.Errorf("ike: %s IDr must use ID_FQDN, got type %d", label, identityType)
  192. }
  193. if identity == "" {
  194. return fmt.Errorf("ike: %s IDr is empty", label)
  195. }
  196. if expectedIDr != "" && !strings.EqualFold(strings.TrimSuffix(identity, "."), strings.TrimSuffix(expectedIDr, ".")) {
  197. return fmt.Errorf("ike: %s IDr %q does not match %q", label, identity, expectedIDr)
  198. }
  199. return nil
  200. }
  201. func parseResponderCertificates(payloads []payload) ([]*x509.Certificate, error) {
  202. var certificates []*x509.Certificate
  203. for _, item := range payloadsOfType(payloads, payloadCert) {
  204. if len(item.Body) < 2 {
  205. return nil, errors.New("ike: responder certificate payload is truncated")
  206. }
  207. if item.Body[0] != 4 {
  208. return nil, fmt.Errorf("ike: unsupported responder certificate encoding %d", item.Body[0])
  209. }
  210. certificate, err := x509.ParseCertificate(item.Body[1:])
  211. if err != nil {
  212. return nil, fmt.Errorf("ike: parse responder certificate: %w", err)
  213. }
  214. certificates = append(certificates, certificate)
  215. }
  216. return certificates, nil
  217. }
  218. func verifyResponderCertificate(certificates []*x509.Certificate, roots *x509.CertPool, serverName string) error {
  219. if len(certificates) == 0 {
  220. return errors.New("ike: no responder certificate")
  221. }
  222. if roots == nil {
  223. var err error
  224. roots, err = x509.SystemCertPool()
  225. if err != nil {
  226. return fmt.Errorf("ike: load system certificate roots: %w", err)
  227. }
  228. }
  229. intermediates := x509.NewCertPool()
  230. for _, certificate := range certificates[1:] {
  231. intermediates.AddCert(certificate)
  232. }
  233. options := x509.VerifyOptions{
  234. Roots: roots,
  235. Intermediates: intermediates,
  236. KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  237. DNSName: strings.TrimSuffix(serverName, "."),
  238. }
  239. if _, err := certificates[0].Verify(options); err != nil {
  240. return fmt.Errorf("ike: verify responder certificate: %w", err)
  241. }
  242. return nil
  243. }
  244. func verifyDigitalAUTH(publicKey crypto.PublicKey, method uint8, signature, signed []byte) error {
  245. switch method {
  246. case authMethodRSASignature:
  247. key, ok := publicKey.(*rsa.PublicKey)
  248. if !ok {
  249. return errors.New("RSA AUTH used with a non-RSA public key")
  250. }
  251. digest := sha1.Sum(signed)
  252. return rsa.VerifyPKCS1v15(key, crypto.SHA1, digest[:], signature)
  253. case authMethodECDSASHA256P256:
  254. return verifyRawECDSA(publicKey, crypto.SHA256, signature, signed)
  255. case authMethodECDSASHA384P384:
  256. return verifyRawECDSA(publicKey, crypto.SHA384, signature, signed)
  257. case authMethodECDSASHA512P521:
  258. return verifyRawECDSA(publicKey, crypto.SHA512, signature, signed)
  259. case authMethodDigitalSignature:
  260. return verifyGenericSignature(publicKey, signature, signed)
  261. default:
  262. return fmt.Errorf("unsupported responder AUTH method %d", method)
  263. }
  264. }
  265. func verifyRawECDSA(publicKey crypto.PublicKey, algorithm crypto.Hash, signature, signed []byte) error {
  266. key, ok := publicKey.(*ecdsa.PublicKey)
  267. if !ok {
  268. return errors.New("ECDSA AUTH used with a non-ECDSA public key")
  269. }
  270. size := (key.Curve.Params().BitSize + 7) / 8
  271. if len(signature) != size*2 {
  272. return fmt.Errorf("ECDSA signature length %d does not match curve size %d", len(signature), size)
  273. }
  274. digest, err := hashSignedOctets(algorithm, signed)
  275. if err != nil {
  276. return err
  277. }
  278. r := new(big.Int).SetBytes(signature[:size])
  279. s := new(big.Int).SetBytes(signature[size:])
  280. if !ecdsa.Verify(key, digest, r, s) {
  281. return errors.New("ECDSA signature verification failed")
  282. }
  283. return nil
  284. }
  285. func verifyGenericSignature(publicKey crypto.PublicKey, encoded, signed []byte) error {
  286. var algorithm pkix.AlgorithmIdentifier
  287. rest, err := asn1.Unmarshal(encoded, &algorithm)
  288. if err != nil || len(rest) == 0 {
  289. return errors.New("generic digital signature has an invalid AlgorithmIdentifier")
  290. }
  291. var hashAlgorithm crypto.Hash
  292. var isRSA bool
  293. switch {
  294. case algorithm.Algorithm.Equal(oidSHA256WithRSA):
  295. hashAlgorithm, isRSA = crypto.SHA256, true
  296. case algorithm.Algorithm.Equal(oidSHA384WithRSA):
  297. hashAlgorithm, isRSA = crypto.SHA384, true
  298. case algorithm.Algorithm.Equal(oidSHA512WithRSA):
  299. hashAlgorithm, isRSA = crypto.SHA512, true
  300. case algorithm.Algorithm.Equal(oidECDSAWithSHA256):
  301. hashAlgorithm = crypto.SHA256
  302. case algorithm.Algorithm.Equal(oidECDSAWithSHA384):
  303. hashAlgorithm = crypto.SHA384
  304. case algorithm.Algorithm.Equal(oidECDSAWithSHA512):
  305. hashAlgorithm = crypto.SHA512
  306. default:
  307. return fmt.Errorf("unsupported generic signature algorithm %s", algorithm.Algorithm.String())
  308. }
  309. digest, err := hashSignedOctets(hashAlgorithm, signed)
  310. if err != nil {
  311. return err
  312. }
  313. if isRSA {
  314. key, ok := publicKey.(*rsa.PublicKey)
  315. if !ok {
  316. return errors.New("RSA signature used with a non-RSA public key")
  317. }
  318. return rsa.VerifyPKCS1v15(key, hashAlgorithm, digest, rest)
  319. }
  320. key, ok := publicKey.(*ecdsa.PublicKey)
  321. if !ok {
  322. return errors.New("ECDSA signature used with a non-ECDSA public key")
  323. }
  324. if !ecdsa.VerifyASN1(key, digest, rest) {
  325. return errors.New("ECDSA generic signature verification failed")
  326. }
  327. return nil
  328. }
  329. func hashSignedOctets(algorithm crypto.Hash, signed []byte) ([]byte, error) {
  330. switch algorithm {
  331. case crypto.SHA1:
  332. sum := sha1.Sum(signed)
  333. return sum[:], nil
  334. case crypto.SHA256:
  335. sum := sha256.Sum256(signed)
  336. return sum[:], nil
  337. case crypto.SHA384:
  338. sum := sha512.Sum384(signed)
  339. return sum[:], nil
  340. case crypto.SHA512:
  341. sum := sha512.Sum512(signed)
  342. return sum[:], nil
  343. default:
  344. return nil, fmt.Errorf("unsupported signature hash %v", algorithm)
  345. }
  346. }
  347. func equalPublicKeys(first, second crypto.PublicKey) bool {
  348. firstDER, firstErr := x509.MarshalPKIXPublicKey(first)
  349. secondDER, secondErr := x509.MarshalPKIXPublicKey(second)
  350. return firstErr == nil && secondErr == nil && bytes.Equal(firstDER, secondDER)
  351. }