You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
6.1 KiB

  1. // Go FIDO U2F Library
  2. // Copyright 2015 The Go FIDO U2F Library Authors. All rights reserved.
  3. // Use of this source code is governed by the MIT
  4. // license that can be found in the LICENSE file.
  5. package u2f
  6. import (
  7. "crypto/ecdsa"
  8. "crypto/elliptic"
  9. "crypto/sha256"
  10. "crypto/x509"
  11. "encoding/asn1"
  12. "encoding/hex"
  13. "errors"
  14. "time"
  15. )
  16. // Registration represents a single enrolment or pairing between an
  17. // application and a token. This data will typically be stored in a database.
  18. type Registration struct {
  19. // Raw serialized registration data as received from the token.
  20. Raw []byte
  21. KeyHandle []byte
  22. PubKey ecdsa.PublicKey
  23. // AttestationCert can be nil for Authenticate requests.
  24. AttestationCert *x509.Certificate
  25. }
  26. // Config contains configurable options for the package.
  27. type Config struct {
  28. // SkipAttestationVerify controls whether the token attestation
  29. // certificate should be verified on registration. Ideally it should
  30. // always be verified. However, there is currently no public list of
  31. // trusted attestation root certificates so it may be necessary to skip.
  32. SkipAttestationVerify bool
  33. // RootAttestationCertPool overrides the default root certificates used
  34. // to verify client attestations. If nil, this defaults to the roots that are
  35. // bundled in this library.
  36. RootAttestationCertPool *x509.CertPool
  37. }
  38. // Register validates a RegisterResponse message to enrol a new token.
  39. // An error is returned if any part of the response fails to validate.
  40. // The returned Registration should be stored by the caller.
  41. func Register(resp RegisterResponse, c Challenge, config *Config) (*Registration, error) {
  42. if config == nil {
  43. config = &Config{}
  44. }
  45. if time.Now().Sub(c.Timestamp) > timeout {
  46. return nil, errors.New("u2f: challenge has expired")
  47. }
  48. regData, err := decodeBase64(resp.RegistrationData)
  49. if err != nil {
  50. return nil, err
  51. }
  52. clientData, err := decodeBase64(resp.ClientData)
  53. if err != nil {
  54. return nil, err
  55. }
  56. reg, sig, err := parseRegistration(regData)
  57. if err != nil {
  58. return nil, err
  59. }
  60. if err := verifyClientData(clientData, c); err != nil {
  61. return nil, err
  62. }
  63. if err := verifyAttestationCert(*reg, config); err != nil {
  64. return nil, err
  65. }
  66. if err := verifyRegistrationSignature(*reg, sig, c.AppID, clientData); err != nil {
  67. return nil, err
  68. }
  69. return reg, nil
  70. }
  71. func parseRegistration(buf []byte) (*Registration, []byte, error) {
  72. if len(buf) < 1+65+1+1+1 {
  73. return nil, nil, errors.New("u2f: data is too short")
  74. }
  75. var r Registration
  76. r.Raw = buf
  77. if buf[0] != 0x05 {
  78. return nil, nil, errors.New("u2f: invalid reserved byte")
  79. }
  80. buf = buf[1:]
  81. x, y := elliptic.Unmarshal(elliptic.P256(), buf[:65])
  82. if x == nil {
  83. return nil, nil, errors.New("u2f: invalid public key")
  84. }
  85. r.PubKey.Curve = elliptic.P256()
  86. r.PubKey.X = x
  87. r.PubKey.Y = y
  88. buf = buf[65:]
  89. khLen := int(buf[0])
  90. buf = buf[1:]
  91. if len(buf) < khLen {
  92. return nil, nil, errors.New("u2f: invalid key handle")
  93. }
  94. r.KeyHandle = buf[:khLen]
  95. buf = buf[khLen:]
  96. // The length of the x509 cert isn't specified so it has to be inferred
  97. // by parsing. We can't use x509.ParseCertificate yet because it returns
  98. // an error if there are any trailing bytes. So parse raw asn1 as a
  99. // workaround to get the length.
  100. sig, err := asn1.Unmarshal(buf, &asn1.RawValue{})
  101. if err != nil {
  102. return nil, nil, err
  103. }
  104. buf = buf[:len(buf)-len(sig)]
  105. fixCertIfNeed(buf)
  106. cert, err := x509.ParseCertificate(buf)
  107. if err != nil {
  108. return nil, nil, err
  109. }
  110. r.AttestationCert = cert
  111. return &r, sig, nil
  112. }
  113. // UnmarshalBinary implements encoding.BinaryMarshaler.
  114. func (r *Registration) UnmarshalBinary(data []byte) error {
  115. reg, _, err := parseRegistration(data)
  116. if err != nil {
  117. return err
  118. }
  119. *r = *reg
  120. return nil
  121. }
  122. // MarshalBinary implements encoding.BinaryUnmarshaler.
  123. func (r *Registration) MarshalBinary() ([]byte, error) {
  124. return r.Raw, nil
  125. }
  126. func verifyAttestationCert(r Registration, config *Config) error {
  127. if config.SkipAttestationVerify {
  128. return nil
  129. }
  130. rootCertPool := roots
  131. if config.RootAttestationCertPool != nil {
  132. rootCertPool = config.RootAttestationCertPool
  133. }
  134. opts := x509.VerifyOptions{Roots: rootCertPool}
  135. _, err := r.AttestationCert.Verify(opts)
  136. return err
  137. }
  138. func verifyRegistrationSignature(
  139. r Registration, signature []byte, appid string, clientData []byte) error {
  140. appParam := sha256.Sum256([]byte(appid))
  141. challenge := sha256.Sum256(clientData)
  142. buf := []byte{0}
  143. buf = append(buf, appParam[:]...)
  144. buf = append(buf, challenge[:]...)
  145. buf = append(buf, r.KeyHandle...)
  146. pk := elliptic.Marshal(r.PubKey.Curve, r.PubKey.X, r.PubKey.Y)
  147. buf = append(buf, pk...)
  148. return r.AttestationCert.CheckSignature(
  149. x509.ECDSAWithSHA256, buf, signature)
  150. }
  151. func getRegisteredKey(appID string, r Registration) RegisteredKey {
  152. return RegisteredKey{
  153. Version: u2fVersion,
  154. KeyHandle: encodeBase64(r.KeyHandle),
  155. AppID: appID,
  156. }
  157. }
  158. // fixCertIfNeed fixes broken certificates described in
  159. // https://github.com/Yubico/php-u2flib-server/blob/master/src/u2flib_server/U2F.php#L84
  160. func fixCertIfNeed(cert []byte) {
  161. h := sha256.Sum256(cert)
  162. switch hex.EncodeToString(h[:]) {
  163. case
  164. "349bca1031f8c82c4ceca38b9cebf1a69df9fb3b94eed99eb3fb9aa3822d26e8",
  165. "dd574527df608e47ae45fbba75a2afdd5c20fd94a02419381813cd55a2a3398f",
  166. "1d8764f0f7cd1352df6150045c8f638e517270e8b5dda1c63ade9c2280240cae",
  167. "d0edc9a91a1677435a953390865d208c55b3183c6759c9b5a7ff494c322558eb",
  168. "6073c436dcd064a48127ddbf6032ac1a66fd59a0c24434f070d4e564c124c897",
  169. "ca993121846c464d666096d35f13bf44c1b05af205f9b4a1e00cf6cc10c5e511":
  170. // clear the offending byte.
  171. cert[len(cert)-257] = 0
  172. }
  173. }
  174. // NewWebRegisterRequest creates a request to enrol a new token.
  175. // regs is the list of the user's existing registration. The browser will
  176. // refuse to re-register a device if it has an existing registration.
  177. func NewWebRegisterRequest(c *Challenge, regs []Registration) *WebRegisterRequest {
  178. req := RegisterRequest{
  179. Version: u2fVersion,
  180. Challenge: encodeBase64(c.Challenge),
  181. }
  182. rr := WebRegisterRequest{
  183. AppID: c.AppID,
  184. RegisterRequests: []RegisterRequest{req},
  185. }
  186. for _, r := range regs {
  187. rk := getRegisteredKey(c.AppID, r)
  188. rr.RegisteredKeys = append(rr.RegisteredKeys, rk)
  189. }
  190. return &rr
  191. }