Rev 44 | Rev 46 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 44 | Rev 45 | ||
---|---|---|---|
Line 22... | Line 22... | ||
22 | include_once __DIR__ . '/misc_functions.inc.php'; |
22 | include_once __DIR__ . '/misc_functions.inc.php'; |
23 | 23 | ||
24 | # --- |
24 | # --- |
25 | 25 | ||
26 | /* |
26 | /* |
27 | #test2('A000000051AABBCC'); |
27 | #test2('A000000051AABBCC'); // International Registration |
28 | #test2('B01234567890'); |
28 | #test2('B01234567890'); // Illegal AID (RFU) |
29 | #test2('D276000098AABBCCDDEEFFAABBCCDDEE'); |
29 | #test2('D276000098AABBCCDDEEFFAABBCCDDEE'); // National Registration |
30 | #test2('F01234567890'); |
30 | #test2('F01234567890'); // Unregistered AID |
31 | #test('91234FFF999'); |
31 | #test('91234FFF999'); // IIN based AID |
32 | #test('51234FFF999'); |
32 | #test('51234FFF999'); // IIN based AID |
33 | #test2('E828BD080F014E585031'); |
33 | test('E828BD080F014E585031'); // ISO E8-OID 1.0.aaaa |
- | 34 | test('E80704007F00070304'); // BSI Illegal E8-OID-AID (with DER Length) |
|
- | 35 | test('E80704007F0007030499'); // BSI Illegal E8-OID-AID + PIX (PIX is never used by BSI; it's just for us to test) |
|
34 | 36 | ||
35 | function test2($aid) { |
37 | function test2($aid) { |
36 | while ($aid != '') { |
38 | while ($aid != '') { |
37 | echo test($aid); |
39 | echo test($aid); |
38 | $aid = substr($aid,0,strlen($aid)-1); |
40 | $aid = substr($aid,0,strlen($aid)-1); |
Line 58... | Line 60... | ||
58 | } |
60 | } |
59 | */ |
61 | */ |
60 | 62 | ||
61 | # --- |
63 | # --- |
62 | 64 | ||
- | 65 | function _aid_e8_oid_helper($output_oid,$by,$ii,&$ret,$minmax_measure,$min,$max) { |
|
- | 66 | if ($minmax_measure == 'ARC') { |
|
- | 67 | if (($min!=-1) && (count($output_oid)<$min)) return true; // continue |
|
- | 68 | if (($max!=-1) && (count($output_oid)>$max)) return false; // stop |
|
- | 69 | } else if ($minmax_measure == 'DER') { |
|
- | 70 | if (($min!=-1) && ($ii+1<$min)) return true; // continue |
|
- | 71 | if (($max!=-1) && ($ii+1>$max)) return false; // stop |
|
- | 72 | } |
|
- | 73 | ||
- | 74 | $byy = $by; |
|
- | 75 | for ($i=0;$i<=$ii;$i++) array_shift($byy); |
|
- | 76 | ||
- | 77 | $is_iso_standard = (count($output_oid) >= 3) && ($output_oid[0] == '1') && ($output_oid[1] == '0'); |
|
- | 78 | ||
- | 79 | $s_oid = implode('.',$output_oid); |
|
- | 80 | ||
- | 81 | if ($is_iso_standard) { |
|
- | 82 | $std_hf = 'Standard ISO/IEC '.$output_oid[2]; |
|
- | 83 | if (isset($output_oid[3])) $std_hf .= "-".$output_oid[3]; |
|
- | 84 | } else { |
|
- | 85 | $std_hf = "Unknown Standard"; // should not happen |
|
- | 86 | } |
|
- | 87 | ||
- | 88 | $pix = implode(':',$byy); |
|
- | 89 | ||
- | 90 | if ($pix !== '') { |
|
- | 91 | $ret[] = array($ii+1,"$std_hf (OID $s_oid)",$pix); |
|
- | 92 | } else { |
|
- | 93 | $ret[] = array($ii+1,"$std_hf (OID $s_oid)",""); |
|
- | 94 | } |
|
- | 95 | ||
- | 96 | return true; |
|
- | 97 | } |
|
- | 98 | ||
63 | function _aid_e8_interpretations($aid) { |
99 | function _aid_e8_interpretations($pure_der, $minmax_measure='ARC', $min=-1, $max=-1) { |
64 | $ret = array(); |
100 | $ret = array(); |
65 | 101 | ||
66 | $output_oid = array(); |
102 | $output_oid = array(); |
67 | 103 | ||
68 | $aid = strtoupper(str_replace(' ','',$aid)); |
104 | $pure_der = strtoupper(str_replace(' ','',$pure_der)); |
69 | $aid = strtoupper(str_replace(':','',$aid)); |
105 | $pure_der = strtoupper(str_replace(':','',$pure_der)); |
70 | $by = str_split($aid,2); |
106 | $by = str_split($pure_der,2); |
71 | if ((array_shift($by) == 'E8') ) { |
- | |
- | 107 | ||
72 | // The following part is partially taken from the DER decoder/encoder by Daniel Marschall: |
108 | // The following part is partially taken from the DER decoder/encoder by Daniel Marschall: |
73 | // https://github.com/danielmarschall/oidconverter/blob/master/php/OidDerConverter.class.phps |
109 | // https://github.com/danielmarschall/oidconverter/blob/master/php/OidDerConverter.class.phps |
74 | // (Only the DER "value" part, without "type" and "length") |
110 | // (Only the DER "value" part, without "type" and "length") |
75 | 111 | ||
76 | $part = 2; // DER part 0 (type) and part 1 (length) not present |
112 | $part = 2; // DER part 0 (type) and part 1 (length) not present |
Line 86... | Line 122... | ||
86 | $first = floor($pb / 40); |
122 | $first = floor($pb / 40); |
87 | $second = $pb % 40; |
123 | $second = $pb % 40; |
88 | if ($first > 2) { |
124 | if ($first > 2) { |
89 | $first = 2; |
125 | $first = 2; |
90 | $output_oid[] = $first; |
126 | $output_oid[] = $first; |
- | 127 | if (!_aid_e8_oid_helper($output_oid, $by, $ii, $ret, $minmax_measure, $min, $max)) break; |
|
91 | $arcBeginning = true; |
128 | $arcBeginning = true; |
92 | 129 | ||
93 | if (($pb & 0x80) != 0) { |
130 | if (($pb & 0x80) != 0) { |
94 | // 2.48 and up => 2+ octets |
131 | // 2.48 and up => 2+ octets |
95 | // Output in "part 3" |
132 | // Output in "part 3" |
Line 105... | Line 142... | ||
105 | $fOK = false; |
142 | $fOK = false; |
106 | } else { |
143 | } else { |
107 | // 2.0 till 2.47 => 1 octet |
144 | // 2.0 till 2.47 => 1 octet |
108 | $second = $pb - 80; |
145 | $second = $pb - 80; |
109 | $output_oid[] = $second; |
146 | $output_oid[] = $second; |
- | 147 | if (!_aid_e8_oid_helper($output_oid, $by, $ii, $ret, $minmax_measure, $min, $max)) break; |
|
110 | $arcBeginning = true; |
148 | $arcBeginning = true; |
111 | $fOK = true; |
149 | $fOK = true; |
112 | $ll = gmp_init(0); |
150 | $ll = gmp_init(0); |
113 | } |
151 | } |
114 | } else { |
152 | } else { |
115 | // 0.0 till 0.37 => 1 octet |
153 | // 0.0 till 0.37 => 1 octet |
116 | // 1.0 till 1.37 => 1 octet |
154 | // 1.0 till 1.37 => 1 octet |
117 | $output_oid[] = $first; |
155 | $output_oid[] = $first; |
118 | $output_oid[] = $second; |
156 | $output_oid[] = $second; |
- | 157 | if (!_aid_e8_oid_helper($output_oid, $by, $ii, $ret, $minmax_measure, $min, $max)) break; |
|
119 | $arcBeginning = true; |
158 | $arcBeginning = true; |
120 | $fOK = true; |
159 | $fOK = true; |
121 | $ll = gmp_init(0); |
160 | $ll = gmp_init(0); |
122 | } |
161 | } |
123 | $part++; |
162 | $part++; |
Line 137... | Line 176... | ||
137 | $ll = gmp_mul($ll, 0x80); |
176 | $ll = gmp_mul($ll, 0x80); |
138 | $ll = gmp_add($ll, $pb); |
177 | $ll = gmp_add($ll, $pb); |
139 | $ll = gmp_sub($ll, $fSub); |
178 | $ll = gmp_sub($ll, $fSub); |
140 | $output_oid[] = gmp_strval($ll, 10); |
179 | $output_oid[] = gmp_strval($ll, 10); |
141 | 180 | ||
142 | $is_iso_standard = ($output_oid[0] == '1') && ($output_oid[1] == '0'); |
181 | if (!_aid_e8_oid_helper($output_oid, $by, $ii, $ret, $minmax_measure, $min, $max)) break; |
143 | - | ||
144 | $byy = $by; |
- | |
145 | for ($i=0;$i<=$ii;$i++) array_shift($byy); |
- | |
146 | - | ||
147 | $s_oid = implode('.',$output_oid); |
- | |
148 | - | ||
149 | if ($is_iso_standard) { |
- | |
150 | $std_hf = 'Standard ISO/IEC '.$output_oid[2]; |
- | |
151 | if (isset($output_oid[3])) $std_hf .= "-".$output_oid[3]; |
- | |
152 | } else { |
- | |
153 | $std_hf = "Unknown Standard"; // should not happen |
- | |
154 | } |
- | |
155 | - | ||
156 | $pix = implode(':',$byy); |
- | |
157 | - | ||
158 | if ($pix !== '') { |
- | |
159 | $ret[] = array($ii+1,"$std_hf (OID $s_oid)",$pix); |
- | |
160 | } else { |
- | |
161 | $ret[] = array($ii+1,"$std_hf (OID $s_oid)",""); |
- | |
162 | } |
- | |
163 | - | ||
164 | // ISO Standards (OID 1.0) will only have 1 or 2 numbers. (Number 1 is the standard, and number 2 |
- | |
165 | // is the part in case of a multi-part standard). |
- | |
166 | if ($is_iso_standard && (count($output_oid) == 4)) break; |
- | |
167 | 182 | ||
168 | // Happens only if 0x80 paddings are allowed |
183 | // Happens only if 0x80 paddings are allowed |
169 | // $fOK = gmp_cmp($ll, 0) >= 0; |
184 | // $fOK = gmp_cmp($ll, 0) >= 0; |
170 | $ll = gmp_init(0); |
185 | $ll = gmp_init(0); |
171 | $fSub = 0; |
186 | $fSub = 0; |
172 | $arcBeginning = true; |
187 | $arcBeginning = true; |
173 | } |
188 | } |
174 | } |
189 | } |
175 | } |
190 | } |
176 | } |
191 | |
177 | return $ret; |
192 | return $ret; |
178 | } |
193 | } |
179 | 194 | ||
180 | function decode_aid($aid,$compact=true) { |
195 | function decode_aid($aid,$compact=true) { |
181 | $sout = ''; |
196 | $sout = ''; |
- | 197 | if (strtolower(substr($aid,0,2)) == '0x') $aid = substr($aid,2); |
|
182 | $out = _decode_aid($aid); |
198 | $out = _decode_aid($aid); |
183 | if ($compact) { |
199 | if ($compact) { |
184 | $max_key_len = 0; |
200 | $max_key_len = 0; |
185 | foreach ($out as $a) { |
201 | foreach ($out as $a) { |
186 | if (is_array($a)) { |
202 | if (is_array($a)) { |
Line 205... | Line 221... | ||
205 | } |
221 | } |
206 | 222 | ||
207 | function _decode_aid($aid) { |
223 | function _decode_aid($aid) { |
208 | 224 | ||
209 | // based on https://github.com/thephpleague/iso3166/blob/main/src/ISO3166.php |
225 | // based on https://github.com/thephpleague/iso3166/blob/main/src/ISO3166.php |
210 | // commit 26.07.2022 |
226 | // commit 26 July 2022 |
211 | // Generated using: |
227 | // Generated using: |
212 | /* |
228 | /* |
213 | $x = new ISO3166(); |
229 | $x = new ISO3166(); |
214 | $bla = $x->all(); |
230 | $bla = $x->all(); |
215 | foreach ($bla as $data) { |
231 | foreach ($bla as $data) { |
Line 690... | Line 706... | ||
690 | 706 | ||
691 | $std_schema = substr($aid,1,1); |
707 | $std_schema = substr($aid,1,1); |
692 | if ($std_schema == '8') { |
708 | if ($std_schema == '8') { |
693 | $out[] = array(" $std_schema", "Standard identified by OID"); |
709 | $out[] = array(" $std_schema", "Standard identified by OID"); |
694 | 710 | ||
- | 711 | // Including the DER Encoding "Length" is not defined by ISO but used illegally |
|
- | 712 | // by German BSI (beside the fact that ISO never allowed anyone else to use E8-AIDs outside |
|
- | 713 | // of OID arc 1.0), |
|
- | 714 | // e.g. 0xE80704007F00070302 defined by "BSI TR-03110" was intended to represent 0.4.0.127.0.7.3.2 |
|
- | 715 | // "more correct" would have been 0xE804007F00070302 |
|
- | 716 | // 0xE80704007F00070304 defined by "BSI TR-03109-2" was intended to represent 0.4.0.127.0.7.3.4 |
|
- | 717 | // "more correct" would have been 0xE804007F00070304 |
|
- | 718 | $include_der_length_roots = array( |
|
- | 719 | '04007F0007' /* bsi-de (0.4.0.127.0.7) */ |
|
- | 720 | ); |
|
- | 721 | $include_der_length = false; |
|
- | 722 | foreach ($include_der_length_roots as $include_der_length_root) { |
|
- | 723 | $der_length_hex = null; |
|
- | 724 | $der_length_dec = null; |
|
- | 725 | if (substr($aid,4,strlen($include_der_length_root)) == $include_der_length_root) { |
|
- | 726 | $der_length_hex = substr($aid,2,2); |
|
- | 727 | $der_length_dec = hexdec($der_length_hex); |
|
- | 728 | if ($der_length_dec <= 14) { |
|
- | 729 | $include_der_length = true; |
|
- | 730 | break; |
|
- | 731 | } |
|
- | 732 | } |
|
- | 733 | } |
|
- | 734 | if ($include_der_length) { |
|
- | 735 | $out[] = array(" $der_length_hex", "DER encoding length (illegal usage not defined by ISO)"); |
|
- | 736 | $pure_der = substr($aid,4); |
|
- | 737 | $indent = 4; |
|
- | 738 | $e8_minmax_measure = 'DER'; |
|
- | 739 | $e8_min = $der_length_dec; |
|
- | 740 | $e8_max = $der_length_dec; |
|
- | 741 | } else { |
|
695 | $data = substr($aid,2); |
742 | $pure_der = substr($aid,2); |
- | 743 | $indent = 2; |
|
- | 744 | // ISO Standards (OID 1.0) will only have 1 or 2 numbers. (Number 1 is the standard, and number 2 |
|
- | 745 | // is the part in case of a multi-part standard). |
|
- | 746 | $e8_minmax_measure = 'ARC'; |
|
- | 747 | $e8_min = 3; // 1.0.aaaa (ISO AAAA) |
|
- | 748 | $e8_max = 4; // 1.0.aaaa.b (ISO AAAA-B) |
|
- | 749 | } |
|
- | 750 | // --- End of BSI compatibility hack --- |
|
- | 751 | ||
696 | try { |
752 | try { |
697 | $interpretations = _aid_e8_interpretations($aid); |
753 | $interpretations = _aid_e8_interpretations($pure_der,$e8_minmax_measure,$e8_min,$e8_max); |
698 | foreach ($interpretations as $ii => $interpretation) { |
754 | foreach ($interpretations as $ii => $interpretation) { |
699 | $pos = $interpretation[0]; |
755 | $pos = $interpretation[0]; |
700 | $txt1 = $interpretation[1]; // Standard |
756 | $txt1 = $interpretation[1]; // Standard |
701 | $txt2 = $interpretation[2]; // PIX (optional) |
757 | $txt2 = $interpretation[2]; // PIX (optional) |
702 | 758 | ||
703 | $aid1 = ' '.substr($aid,2,$pos*2); |
759 | $aid1 = str_repeat(' ',$indent).substr($pure_der,0,$pos*2); |
704 | $aid2 = substr($aid,2+$pos*2); |
760 | $aid2 = substr($pure_der,$pos*2); |
705 | 761 | ||
706 | $out[] = array("$aid1", "$txt1"); |
762 | $out[] = array("$aid1", "$txt1"); |
707 | if ($txt2 !== '') { |
763 | if ($txt2 !== '') { |
708 | $pix = "$txt2 (".c_literal_hexstr(str_replace(':','',$txt2)).")"; |
764 | $pix = "$txt2 (".c_literal_hexstr(str_replace(':','',$txt2)).")"; |
709 | $out[] = array(str_repeat(' ',strlen($aid1))."$aid2", "with PIX $pix"); |
765 | $out[] = array(str_repeat(' ',strlen($aid1))."$aid2", "with PIX $pix"); |
Line 711... | Line 767... | ||
711 | if ($ii < count($interpretations)-1) { |
767 | if ($ii < count($interpretations)-1) { |
712 | $out[] = array('', 'or:'); |
768 | $out[] = array('', 'or:'); |
713 | } |
769 | } |
714 | } |
770 | } |
715 | } catch (Exception $e) { |
771 | } catch (Exception $e) { |
716 | $out[] = array(" $data", "ERROR: ".$e->getMessage()); |
772 | $out[] = array(str_repeat(' ',$indent).$pure_der, "ERROR: ".$e->getMessage()); |
717 | - | ||
718 | } |
773 | } |
719 | } else if ($std_schema != '') { |
774 | } else if ($std_schema != '') { |
720 | // E0..E7, E9..EF are RFU |
775 | // E0..E7, E9..EF are RFU |
721 | $unknown = substr($aid,1); |
776 | $unknown = substr($aid,1); |
722 | $out[] = array(" $unknown", "ILLEGAL USAGE / RESERVED"); |
777 | $out[] = array(" $unknown", "ILLEGAL USAGE / RESERVED"); |