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
|