webauthn 2.1.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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