File: authorization_list.rb

package info (click to toggle)
ruby-android-key-attestation 0.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 216 kB
  • sloc: ruby: 352; makefile: 7; sh: 4
file content (107 lines) | stat: -rw-r--r-- 2,713 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# frozen_string_literal: true

module AndroidKeyAttestation
  class AuthorizationList
    # https://source.android.com/security/keystore/attestation#attestation-extension
    PURPOSE_TAG = 1
    ALGORITHM_TAG = 2
    KEY_SIZE_TAG = 3
    DIGEST_TAG = 5
    PADDING_TAG = 6
    EC_CURVE_TAG = 10
    RSA_PUBLIC_EXPONENT_TAG = 200
    ROLLBACK_RESISTANCE_TAG = 303
    ACTIVE_DATE_TIME_TAG = 400
    ORIGINATION_EXPIRE_DATE_TIME_TAG = 401
    USAGE_EXPIRE_DATE_TIME_TAG = 402
    NO_AUTH_REQUIRED_TAG = 503
    USER_AUTH_TYPE_TAG = 504
    AUTH_TIMEOUT_TAG = 505
    ALLOW_WHILE_ON_BODY_TAG = 506
    TRUSTED_USER_PRESENCE_REQUIRED_TAG = 507
    TRUSTED_CONFIRMATION_REQUIRED_TAG = 508
    UNLOCK_DEVICE_REQUIRED_TAG = 509
    ALL_APPLICATIONS_TAG = 600
    APPLICATION_ID_TAG = 601
    CREATION_DATE_TIME_TAG = 701
    ORIGIN_TAG = 702
    ROOT_OF_TRUST_TAG = 704
    OS_VERSION_TAG = 705
    OS_PATCH_LEVEL_TAG = 706
    ATTESTATION_APPLICATION_ID_TAG = 709
    ATTESTATION_ID_BRAND_TAG = 710
    ATTESTATION_ID_DEVICE_TAG = 711
    ATTESTATION_ID_PRODUCT_TAG = 712
    ATTESTATION_ID_SERIAL_TAG = 713
    ATTESTATION_ID_IMEI_TAG = 714
    ATTESTATION_ID_MEID_TAG = 715
    ATTESTATION_ID_MANUFACTURER_TAG = 716
    ATTESTATION_ID_MODEL_TAG = 717
    VENDOR_PATCH_LEVEL_TAG = 718
    BOOT_PATCH_LEVEL_TAG = 719

    # https://source.android.com/security/keystore/tags
    PURPOSE_ENUM = {
      0 => :encrypt,
      1 => :decrypt,
      2 => :sign,
      3 => :verify,
      4 => :derive_key,
      5 => :wrap_key,
    }.freeze
    ORIGIN_ENUM = {
      0 => :generated,
      1 => :derived,
      2 => :imported,
      3 => :unknown,
    }.freeze

    def initialize(sequence)
      @sequence = sequence
    end

    def purpose
      integers = find_optional_integer_set(PURPOSE_TAG)
      integers&.map { |i| PURPOSE_ENUM.fetch(i) }
    end

    def all_applications
      find_boolean(ALL_APPLICATIONS_TAG)
    end

    def creation_date
      find_time_milliseconds(CREATION_DATE_TIME_TAG)
    end

    def origin
      integer = find_optional_integer(ORIGIN_TAG)
      ORIGIN_ENUM.fetch(integer) if integer
    end

    def find_by_tag(tag)
      sequence.detect { |data| data.tag == tag }
    end

    private

    attr_reader :sequence

    def find_optional_integer_set(tag)
      value = find_by_tag(tag)&.value&.at(0)&.value
      value&.map { |asn1_int| asn1_int.value.to_i }
    end

    def find_optional_integer(tag)
      find_by_tag(tag)&.value&.at(0)&.value&.to_i
    end

    def find_boolean(tag)
      find_by_tag(tag)&.value || false
    end

    def find_time_milliseconds(tag)
      value = find_by_tag(tag)&.value&.at(0)&.value
      Time.at(value.to_i / 1000) if value
    end
  end
end