webauthn 2.1.0 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +113 -13
  3. data/.travis.yml +21 -18
  4. data/Appraisals +4 -0
  5. data/CHANGELOG.md +41 -0
  6. data/CONTRIBUTING.md +0 -5
  7. data/README.md +70 -8
  8. data/SECURITY.md +6 -4
  9. data/gemfiles/openssl_2_2.gemfile +7 -0
  10. data/lib/cose/rsapkcs1_algorithm.rb +50 -0
  11. data/lib/webauthn/attestation_object.rb +43 -0
  12. data/lib/webauthn/attestation_statement.rb +20 -20
  13. data/lib/webauthn/attestation_statement/android_key.rb +28 -30
  14. data/lib/webauthn/attestation_statement/android_safetynet.rb +27 -7
  15. data/lib/webauthn/attestation_statement/base.rb +108 -10
  16. data/lib/webauthn/attestation_statement/fido_u2f.rb +8 -6
  17. data/lib/webauthn/attestation_statement/none.rb +7 -1
  18. data/lib/webauthn/attestation_statement/packed.rb +13 -41
  19. data/lib/webauthn/attestation_statement/tpm.rb +38 -75
  20. data/lib/webauthn/authenticator_assertion_response.rb +3 -7
  21. data/lib/webauthn/authenticator_attestation_response.rb +19 -84
  22. data/lib/webauthn/authenticator_data.rb +51 -51
  23. data/lib/webauthn/authenticator_data/attested_credential_data.rb +29 -50
  24. data/lib/webauthn/authenticator_response.rb +3 -0
  25. data/lib/webauthn/credential_creation_options.rb +2 -0
  26. data/lib/webauthn/credential_request_options.rb +2 -0
  27. data/lib/webauthn/fake_authenticator.rb +7 -3
  28. data/lib/webauthn/fake_authenticator/attestation_object.rb +7 -3
  29. data/lib/webauthn/fake_authenticator/authenticator_data.rb +2 -4
  30. data/lib/webauthn/fake_client.rb +19 -5
  31. data/lib/webauthn/public_key.rb +21 -2
  32. data/lib/webauthn/public_key_credential.rb +13 -3
  33. data/lib/webauthn/u2f_migrator.rb +5 -4
  34. data/lib/webauthn/version.rb +1 -1
  35. data/script/ci/install-openssl +7 -0
  36. data/script/ci/install-ruby +13 -0
  37. data/webauthn.gemspec +13 -9
  38. metadata +54 -41
  39. data/lib/android_safetynet/attestation_response.rb +0 -116
  40. data/lib/cose/rsassa_algorithm.rb +0 -10
  41. data/lib/tpm/constants.rb +0 -44
  42. data/lib/tpm/s_attest.rb +0 -26
  43. data/lib/tpm/s_attest/s_certify_info.rb +0 -14
  44. data/lib/tpm/sized_buffer.rb +0 -13
  45. data/lib/tpm/t_public.rb +0 -32
  46. data/lib/tpm/t_public/s_ecc_parms.rb +0 -17
  47. data/lib/tpm/t_public/s_rsa_parms.rb +0 -17
  48. data/lib/webauthn/attestation_statement/android_key/authorization_list.rb +0 -39
  49. data/lib/webauthn/attestation_statement/android_key/key_description.rb +0 -37
  50. data/lib/webauthn/attestation_statement/tpm/cert_info.rb +0 -44
  51. data/lib/webauthn/attestation_statement/tpm/pub_area.rb +0 -85
  52. data/lib/webauthn/signature_verifier.rb +0 -77
@@ -4,7 +4,6 @@ require "cose"
4
4
  require "openssl"
5
5
  require "webauthn/attestation_statement/base"
6
6
  require "webauthn/attestation_statement/fido_u2f/public_key"
7
- require "webauthn/signature_verifier"
8
7
 
9
8
  module WebAuthn
10
9
  module AttestationStatement
@@ -19,7 +18,8 @@ module WebAuthn
19
18
  valid_credential_public_key?(authenticator_data.credential.public_key) &&
20
19
  valid_aaguid?(authenticator_data.attested_credential_data.raw_aaguid) &&
21
20
  valid_signature?(authenticator_data, client_data_hash) &&
22
- [WebAuthn::AttestationStatement::ATTESTATION_TYPE_BASIC_OR_ATTCA, attestation_trust_path]
21
+ trustworthy?(attestation_certificate_key_id: attestation_certificate_key_id) &&
22
+ [attestation_type, attestation_trust_path]
23
23
  end
24
24
 
25
25
  private
@@ -47,10 +47,8 @@ module WebAuthn
47
47
  attested_credential_data_aaguid == WebAuthn::AuthenticatorData::AttestedCredentialData::ZEROED_AAGUID
48
48
  end
49
49
 
50
- def valid_signature?(authenticator_data, client_data_hash)
51
- WebAuthn::SignatureVerifier
52
- .new(VALID_ATTESTATION_CERTIFICATE_ALGORITHM, certificate_public_key)
53
- .verify(signature, verification_data(authenticator_data, client_data_hash))
50
+ def algorithm
51
+ VALID_ATTESTATION_CERTIFICATE_ALGORITHM.id
54
52
  end
55
53
 
56
54
  def verification_data(authenticator_data, client_data_hash)
@@ -64,6 +62,10 @@ module WebAuthn
64
62
  def public_key_u2f(cose_key_data)
65
63
  PublicKey.new(cose_key_data)
66
64
  end
65
+
66
+ def attestation_type
67
+ WebAuthn::AttestationStatement::ATTESTATION_TYPE_BASIC_OR_ATTCA
68
+ end
67
69
  end
68
70
  end
69
71
  end
@@ -6,12 +6,18 @@ module WebAuthn
6
6
  module AttestationStatement
7
7
  class None < Base
8
8
  def valid?(*_args)
9
- if statement == {}
9
+ if statement == {} && trustworthy?
10
10
  [WebAuthn::AttestationStatement::ATTESTATION_TYPE_NONE, nil]
11
11
  else
12
12
  false
13
13
  end
14
14
  end
15
+
16
+ private
17
+
18
+ def attestation_type
19
+ WebAuthn::AttestationStatement::ATTESTATION_TYPE_NONE
20
+ end
15
21
  end
16
22
  end
17
23
  end
@@ -2,25 +2,21 @@
2
2
 
3
3
  require "openssl"
4
4
  require "webauthn/attestation_statement/base"
5
- require "webauthn/signature_verifier"
6
5
 
7
6
  module WebAuthn
8
7
  # Implements https://www.w3.org/TR/2018/CR-webauthn-20180807/#packed-attestation
9
- # ECDAA attestation is unsupported.
10
8
  module AttestationStatement
11
9
  class Packed < Base
12
10
  # Follows "Verification procedure"
13
11
  def valid?(authenticator_data, client_data_hash)
14
- check_unsupported_feature
15
-
16
12
  valid_format? &&
17
13
  valid_algorithm?(authenticator_data.credential) &&
18
- valid_certificate_chain? &&
19
14
  valid_ec_public_keys?(authenticator_data.credential) &&
20
15
  meet_certificate_requirement? &&
21
16
  matching_aaguid?(authenticator_data.attested_credential_data.raw_aaguid) &&
22
17
  valid_signature?(authenticator_data, client_data_hash) &&
23
- attestation_type_and_trust_path
18
+ trustworthy?(aaguid: authenticator_data.aaguid) &&
19
+ [attestation_type, attestation_trust_path]
24
20
  end
25
21
 
26
22
  private
@@ -30,27 +26,11 @@ module WebAuthn
30
26
  end
31
27
 
32
28
  def self_attestation?
33
- !raw_certificates && !raw_ecdaa_key_id
29
+ !raw_certificates
34
30
  end
35
31
 
36
32
  def valid_format?
37
- algorithm && signature && (
38
- [raw_certificates, raw_ecdaa_key_id].compact.size < 2
39
- )
40
- end
41
-
42
- def check_unsupported_feature
43
- if raw_ecdaa_key_id
44
- raise NotSupportedError, "ecdaaKeyId of the packed attestation format is not implemented yet"
45
- end
46
- end
47
-
48
- def valid_certificate_chain?
49
- if certificate_chain
50
- certificate_chain.all? { |c| certificate_in_use?(c) }
51
- else
52
- true
53
- end
33
+ algorithm && signature
54
34
  end
55
35
 
56
36
  def valid_ec_public_keys?(credential)
@@ -65,7 +45,6 @@ module WebAuthn
65
45
  subject = attestation_certificate.subject.to_a
66
46
 
67
47
  attestation_certificate.version == 2 &&
68
- certificate_in_use?(attestation_certificate) &&
69
48
  subject.assoc('OU')&.at(1) == "Authenticator Attestation" &&
70
49
  attestation_certificate.extensions.find { |ext| ext.oid == 'basicConstraints' }&.value == 'CA:FALSE'
71
50
  else
@@ -73,27 +52,20 @@ module WebAuthn
73
52
  end
74
53
  end
75
54
 
76
- def certificate_in_use?(certificate)
77
- now = Time.now
78
-
79
- certificate.not_before < now && now < certificate.not_after
55
+ def attestation_type
56
+ if attestation_trust_path
57
+ WebAuthn::AttestationStatement::ATTESTATION_TYPE_BASIC_OR_ATTCA # FIXME: use metadata if available
58
+ else
59
+ WebAuthn::AttestationStatement::ATTESTATION_TYPE_SELF
60
+ end
80
61
  end
81
62
 
82
63
  def valid_signature?(authenticator_data, client_data_hash)
83
- signature_verifier = WebAuthn::SignatureVerifier.new(
84
- algorithm,
64
+ super(
65
+ authenticator_data,
66
+ client_data_hash,
85
67
  attestation_certificate&.public_key || authenticator_data.credential.public_key_object
86
68
  )
87
-
88
- signature_verifier.verify(signature, authenticator_data.data + client_data_hash)
89
- end
90
-
91
- def attestation_type_and_trust_path
92
- if attestation_trust_path
93
- [WebAuthn::AttestationStatement::ATTESTATION_TYPE_BASIC_OR_ATTCA, attestation_trust_path]
94
- else
95
- [WebAuthn::AttestationStatement::ATTESTATION_TYPE_SELF, nil]
96
- end
97
69
  end
98
70
  end
99
71
  end
@@ -2,98 +2,63 @@
2
2
 
3
3
  require "cose/algorithm"
4
4
  require "openssl"
5
- require "tpm/constants"
5
+ require "tpm/key_attestation"
6
6
  require "webauthn/attestation_statement/base"
7
- require "webauthn/attestation_statement/tpm/cert_info"
8
- require "webauthn/attestation_statement/tpm/pub_area"
9
- require "webauthn/signature_verifier"
10
7
 
11
8
  module WebAuthn
12
9
  module AttestationStatement
13
10
  class TPM < Base
14
- CERTIFICATE_V3 = 2
15
- CERTIFICATE_EMPTY_NAME = OpenSSL::X509::Name.new([]).freeze
16
- CERTIFICATE_SAN_DIRECTORY_NAME = 4
17
- OID_TCG_AT_TPM_MANUFACTURER = "2.23.133.2.1"
18
- OID_TCG_AT_TPM_MODEL = "2.23.133.2.2"
19
- OID_TCG_AT_TPM_VERSION = "2.23.133.2.3"
20
- OID_TCG_KP_AIK_CERTIFICATE = "2.23.133.8.3"
21
11
  TPM_V2 = "2.0"
22
12
 
23
- def valid?(authenticator_data, client_data_hash)
24
- case attestation_type
25
- when ATTESTATION_TYPE_ATTCA
26
- att_to_be_signed = authenticator_data.data + client_data_hash
13
+ COSE_ALG_TO_TPM = {
14
+ "RS1" => { signature: ::TPM::ALG_RSASSA, hash: ::TPM::ALG_SHA1 },
15
+ "RS256" => { signature: ::TPM::ALG_RSASSA, hash: ::TPM::ALG_SHA256 },
16
+ "PS256" => { signature: ::TPM::ALG_RSAPSS, hash: ::TPM::ALG_SHA256 },
17
+ "ES256" => { signature: ::TPM::ALG_ECDSA, hash: ::TPM::ALG_SHA256 },
18
+ }.freeze
27
19
 
20
+ def valid?(authenticator_data, client_data_hash)
21
+ attestation_type == ATTESTATION_TYPE_ATTCA &&
28
22
  ver == TPM_V2 &&
29
- valid_signature? &&
30
- valid_attestation_certificate? &&
31
- pub_area.valid?(authenticator_data.credential.public_key) &&
32
- cert_info.valid?(statement["pubArea"],
33
- OpenSSL::Digest.digest(cose_algorithm.hash_function, att_to_be_signed)) &&
34
- matching_aaguid?(authenticator_data.attested_credential_data.raw_aaguid) &&
35
- [attestation_type, attestation_trust_path]
36
- when ATTESTATION_TYPE_ECDAA
37
- raise(
38
- WebAuthn::AttestationStatement::Base::NotSupportedError,
39
- "Attestation type ECDAA is not supported"
40
- )
41
- end
23
+ valid_key_attestation?(
24
+ authenticator_data.data + client_data_hash,
25
+ authenticator_data.credential.public_key_object,
26
+ authenticator_data.aaguid
27
+ ) &&
28
+ matching_aaguid?(authenticator_data.attested_credential_data.raw_aaguid) &&
29
+ trustworthy?(aaguid: authenticator_data.aaguid) &&
30
+ [attestation_type, attestation_trust_path]
42
31
  end
43
32
 
44
33
  private
45
34
 
46
- def valid_signature?
47
- WebAuthn::SignatureVerifier
48
- .new(algorithm, attestation_certificate.public_key)
49
- .verify(signature, verification_data, rsa_pss_salt_length: :auto)
50
- end
51
-
52
- def valid_attestation_certificate?
53
- extensions = attestation_certificate.extensions
54
-
55
- attestation_certificate.version == CERTIFICATE_V3 &&
56
- attestation_certificate.subject.eql?(CERTIFICATE_EMPTY_NAME) &&
57
- valid_subject_alternative_name? &&
58
- certificate_in_use?(attestation_certificate) &&
59
- extensions.find { |ext| ext.oid == 'basicConstraints' }&.value == "CA:FALSE" &&
60
- extensions.find { |ext| ext.oid == "extendedKeyUsage" }&.value == OID_TCG_KP_AIK_CERTIFICATE
61
- end
62
-
63
- def valid_subject_alternative_name?
64
- extension = attestation_certificate.extensions.detect { |ext| ext.oid == "subjectAltName" }
65
- return unless extension&.critical?
66
-
67
- san_asn1 = OpenSSL::ASN1.decode(extension).find do |val|
68
- val.tag_class == :UNIVERSAL && val.tag == OpenSSL::ASN1::OCTET_STRING
69
- end
70
- directory_name = OpenSSL::ASN1.decode(san_asn1.value).find do |val|
71
- val.tag_class == :CONTEXT_SPECIFIC && val.tag == CERTIFICATE_SAN_DIRECTORY_NAME
72
- end
73
- name = OpenSSL::X509::Name.new(directory_name.value.first).to_a
74
- manufacturer = name.assoc(OID_TCG_AT_TPM_MANUFACTURER).at(1)
75
- model = name.assoc(OID_TCG_AT_TPM_MODEL).at(1)
76
- version = name.assoc(OID_TCG_AT_TPM_VERSION).at(1)
77
-
78
- ::TPM::VENDOR_IDS[manufacturer] && !model.empty? && !version.empty?
79
- end
80
-
81
- def certificate_in_use?(certificate)
82
- now = Time.now
35
+ def valid_key_attestation?(certified_extra_data, key, aaguid)
36
+ key_attestation =
37
+ ::TPM::KeyAttestation.new(
38
+ statement["certInfo"],
39
+ signature,
40
+ statement["pubArea"],
41
+ certificates,
42
+ OpenSSL::Digest.digest(cose_algorithm.hash_function, certified_extra_data),
43
+ signature_algorithm: tpm_algorithm[:signature],
44
+ hash_algorithm: tpm_algorithm[:hash],
45
+ root_certificates: root_certificates(aaguid: aaguid)
46
+ )
83
47
 
84
- certificate.not_before < now && now < certificate.not_after
48
+ key_attestation.valid? && key_attestation.key && key_attestation.key.to_pem == key.to_pem
85
49
  end
86
50
 
87
- def verification_data
88
- statement["certInfo"]
51
+ def valid_certificate_chain?(**_)
52
+ # Already performed as part of #valid_key_attestation?
53
+ true
89
54
  end
90
55
 
91
- def cert_info
92
- @cert_info ||= CertInfo.new(statement["certInfo"])
56
+ def default_root_certificates
57
+ ::TPM::KeyAttestation::ROOT_CERTIFICATES
93
58
  end
94
59
 
95
- def pub_area
96
- @pub_area ||= PubArea.new(statement["pubArea"])
60
+ def tpm_algorithm
61
+ COSE_ALG_TO_TPM[cose_algorithm.name] || raise("Unsupported algorithm #{cose_algorithm.name}")
97
62
  end
98
63
 
99
64
  def ver
@@ -105,10 +70,8 @@ module WebAuthn
105
70
  end
106
71
 
107
72
  def attestation_type
108
- if raw_certificates && !raw_ecdaa_key_id
73
+ if raw_certificates
109
74
  ATTESTATION_TYPE_ATTCA
110
- elsif raw_ecdaa_key_id && !raw_certificates
111
- ATTESTATION_TYPE_ECDAA
112
75
  else
113
76
  raise "Attestation type invalid"
114
77
  end
@@ -3,7 +3,6 @@
3
3
  require "webauthn/authenticator_data"
4
4
  require "webauthn/authenticator_response"
5
5
  require "webauthn/encoder"
6
- require "webauthn/signature_verifier"
7
6
  require "webauthn/public_key"
8
7
 
9
8
  module WebAuthn
@@ -37,8 +36,7 @@ module WebAuthn
37
36
  @user_handle = user_handle
38
37
  end
39
38
 
40
- def verify(expected_challenge, expected_origin = nil, public_key:, sign_count:, user_verification: nil,
41
- rp_id: nil)
39
+ def verify(expected_challenge, expected_origin = nil, public_key:, sign_count:, user_verification: nil, rp_id: nil)
42
40
  super(expected_challenge, expected_origin, user_verification: user_verification, rp_id: rp_id)
43
41
  verify_item(:signature, WebAuthn::PublicKey.deserialize(public_key))
44
42
  verify_item(:sign_count, sign_count)
@@ -47,7 +45,7 @@ module WebAuthn
47
45
  end
48
46
 
49
47
  def authenticator_data
50
- @authenticator_data ||= WebAuthn::AuthenticatorData.new(authenticator_data_bytes)
48
+ @authenticator_data ||= WebAuthn::AuthenticatorData.deserialize(authenticator_data_bytes)
51
49
  end
52
50
 
53
51
  private
@@ -55,9 +53,7 @@ module WebAuthn
55
53
  attr_reader :authenticator_data_bytes, :signature
56
54
 
57
55
  def valid_signature?(webauthn_public_key)
58
- WebAuthn::SignatureVerifier
59
- .new(webauthn_public_key.alg, webauthn_public_key.pkey)
60
- .verify(signature, authenticator_data_bytes + client_data.hash)
56
+ webauthn_public_key.verify(signature, authenticator_data_bytes + client_data.hash)
61
57
  end
62
58
 
63
59
  def valid_sign_count?(stored_sign_count)
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cbor"
4
+ require "forwardable"
4
5
  require "uri"
5
6
  require "openssl"
6
7
 
7
- require "webauthn/authenticator_data"
8
+ require "webauthn/attestation_object"
8
9
  require "webauthn/authenticator_response"
9
- require "webauthn/attestation_statement"
10
10
  require "webauthn/client_data"
11
11
  require "webauthn/encoder"
12
12
 
@@ -16,6 +16,8 @@ module WebAuthn
16
16
  class AttestedCredentialVerificationError < VerificationError; end
17
17
 
18
18
  class AuthenticatorAttestationResponse < AuthenticatorResponse
19
+ extend Forwardable
20
+
19
21
  def self.from_client(response)
20
22
  encoder = WebAuthn.configuration.encoder
21
23
 
@@ -30,7 +32,7 @@ module WebAuthn
30
32
  def initialize(attestation_object:, **options)
31
33
  super(**options)
32
34
 
33
- @attestation_object = attestation_object
35
+ @attestation_object_bytes = attestation_object
34
36
  end
35
37
 
36
38
  def verify(expected_challenge, expected_origin = nil, user_verification: nil, rp_id: nil)
@@ -39,107 +41,40 @@ module WebAuthn
39
41
  verify_item(:attested_credential)
40
42
  if WebAuthn.configuration.verify_attestation_statement
41
43
  verify_item(:attestation_statement)
42
- verify_item(:attestation_trustworthiness) if WebAuthn.configuration.attestation_root_certificates_finders.any?
43
44
  end
44
45
 
45
46
  true
46
47
  end
47
48
 
48
- def credential
49
- authenticator_data.credential
50
- end
51
-
52
- def attestation_statement
53
- @attestation_statement ||=
54
- WebAuthn::AttestationStatement.from(attestation["fmt"], attestation["attStmt"])
49
+ def attestation_object
50
+ @attestation_object ||= WebAuthn::AttestationObject.deserialize(attestation_object_bytes)
55
51
  end
56
52
 
57
- def authenticator_data
58
- @authenticator_data ||= WebAuthn::AuthenticatorData.new(attestation["authData"])
59
- end
53
+ def_delegators(
54
+ :attestation_object,
55
+ :aaguid,
56
+ :attestation_statement,
57
+ :attestation_certificate_key_id,
58
+ :authenticator_data,
59
+ :credential
60
+ )
60
61
 
61
- def attestation_format
62
- attestation["fmt"]
63
- end
64
-
65
- def attestation
66
- @attestation ||= CBOR.decode(attestation_object)
67
- end
68
-
69
- def aaguid
70
- raw_aaguid = authenticator_data.attested_credential_data.raw_aaguid
71
- unless raw_aaguid == WebAuthn::AuthenticatorData::AttestedCredentialData::ZEROED_AAGUID
72
- authenticator_data.attested_credential_data.aaguid
73
- end
74
- end
75
-
76
- def attestation_certificate_key
77
- raw_subject_key_identifier(attestation_statement.attestation_certificate)&.unpack("H*")&.[](0)
78
- end
62
+ alias_method :attestation_certificate_key, :attestation_certificate_key_id
79
63
 
80
64
  private
81
65
 
82
- attr_reader :attestation_object
66
+ attr_reader :attestation_object_bytes
83
67
 
84
68
  def type
85
69
  WebAuthn::TYPES[:create]
86
70
  end
87
71
 
88
72
  def valid_attested_credential?
89
- authenticator_data.attested_credential_data_included? &&
90
- authenticator_data.attested_credential_data.valid?
73
+ attestation_object.valid_attested_credential?
91
74
  end
92
75
 
93
76
  def valid_attestation_statement?
94
- @attestation_type, @attestation_trust_path = attestation_statement.valid?(authenticator_data, client_data.hash)
95
- end
96
-
97
- def valid_attestation_trustworthiness?
98
- case @attestation_type
99
- when WebAuthn::AttestationStatement::ATTESTATION_TYPE_NONE
100
- WebAuthn.configuration.acceptable_attestation_types.include?('None')
101
- when WebAuthn::AttestationStatement::ATTESTATION_TYPE_SELF
102
- WebAuthn.configuration.acceptable_attestation_types.include?('Self')
103
- else
104
- WebAuthn.configuration.acceptable_attestation_types.include?(@attestation_type) &&
105
- attestation_root_certificates_store.verify(leaf_certificate, signing_certificates)
106
- end
107
- end
108
-
109
- def raw_subject_key_identifier(certificate)
110
- extension = certificate.extensions.detect { |ext| ext.oid == "subjectKeyIdentifier" }
111
- return unless extension
112
-
113
- ext_asn1 = OpenSSL::ASN1.decode(extension.to_der)
114
- ext_value = ext_asn1.value.last
115
- OpenSSL::ASN1.decode(ext_value.value).value
116
- end
117
-
118
- def attestation_root_certificates_store
119
- certificates =
120
- WebAuthn.configuration.attestation_root_certificates_finders.reduce([]) do |certs, finder|
121
- if certs.empty?
122
- finder.find(attestation_format: attestation_format,
123
- aaguid: aaguid,
124
- attestation_certificate_key_id: attestation_certificate_key) || []
125
- else
126
- certs
127
- end
128
- end
129
-
130
- OpenSSL::X509::Store.new.tap do |store|
131
- certificates.each do |cert|
132
- store.add_cert(cert)
133
- end
134
- end
135
- end
136
-
137
- def signing_certificates
138
- @attestation_trust_path[1..-1]
139
- end
140
-
141
- def leaf_certificate
142
- @attestation_trust_path.first
77
+ @attestation_type, @attestation_trust_path = attestation_object.valid_attestation_statement?(client_data.hash)
143
78
  end
144
79
  end
145
80
  end