33,6 → 33,7 |
test('E828BD080F014E585031'); // ISO E8-OID 1.0.aaaa |
test('E80704007F00070304'); // BSI Illegal E8-OID-AID (with DER Length) |
test('E80704007F0007030499'); // BSI Illegal E8-OID-AID + PIX (PIX is never used by BSI; it's just for us to test) |
test('E829112233'); // Possible other illegal E8-OID |
|
function test2($aid) { |
while ($aid != '') { |
192,6 → 193,79 |
return $ret; |
} |
|
function _aid_e8_length_usage($aid) { |
// Return true if $aid is most likely E8+Length+OID (not intended by ISO) |
// Return false if $aid is most likely E8+OID (defined by ISO for their OID 1.0) |
// Return null if it is ambiguous |
|
assert(substr($aid,0,2) === 'E8'); |
$len = substr($aid,2,2); |
$rest = substr($aid,4); |
$rest_num_bytes = floor(strlen($rest)/2); |
|
$is_e8_len_oid = false; |
$is_e8_oid = false; |
|
// There are not enough following bytes, so it cannot be E8+Length+OID. It must be E8+OID |
if ($len > $rest_num_bytes) $is_e8_oid = true; |
|
// E8 00 ... must be E8+OID, with OID 0.0.xx (recommendation), because Length=0 is not possible |
if ($len == 0) $is_e8_oid = true; |
|
// E8 01 ... must be E8+Length+OID, because OID 0.1 (question) was never used |
if ($len == 1) $is_e8_len_oid = true; |
|
// E8 02 refers to OID 0.2 (administration) but could also refer to a length |
//if ($len == 2) return null; |
|
// E8 03 refers to OID 0.3 (network-operator) but could also refer to a length |
//if ($len == 3) return null; |
|
// E8 04 refers to OID 0.4 (identified-organization) but could also refer to a length |
//if ($len == 4) return null; |
|
// E8 05 refers to OID 0.5 (r-recommendation) but could also refer to a length |
//if ($len == 5) return null; |
|
// E8 06-08 refers to OID 0.6-8, which are not defined, E8+Length+OID |
if (($len >= 6) && ($len <= 8)) $is_e8_len_oid = true; |
|
// E8 09 refers to OID 0.9, which can be an OID or a Length |
if ($len == 9) { |
// The only legal child of OID 0.9 is OID 0.9.2342 ($len=09, $rest=9226); then it is E8+OID |
// An OID beginning with DER encoding 9226 would be 2.2262, which is very unlikely |
if (substr($rest,0,4) === '9226') { |
// 09 92 26 is OID 0.9.2342, which is a valid OID (the only valid OID) => valid OID |
// 92 26 would be OID 2.2262 which is most likely not a valid OID => invalid Len |
$is_e8_oid = true; |
} else { |
// Any other child inside 0.9 except for 2342 is illegal, so it must be length |
$is_e8_len_oid = true; |
} |
} |
|
// E8 10-14 refers to OID 0.10-14 which is not defined. Therefore it must be E8+Length+OID |
if (($len >= 10) && ($len <= 14)) $is_e8_len_oid = true; |
|
// If E8+Length+OID, then Len can max be 14, because E8 takes 1 byte, length takes 1 byte, and AID must be max 16 bytes |
if ($len > 14) $is_e8_oid = true; |
|
// There is at least one case where the usage of E8+Length+OID is known: |
// Including the DER Encoding "Length" is not defined by ISO but used illegally |
// by German BSI (beside the fact that ISO never allowed anyone else to use E8-AIDs outside |
// of OID arc 1.0), |
// e.g. AID E80704007F00070302 defined by "BSI TR-03110" was intended to represent 0.4.0.127.0.7.3.2 |
// "more correct" would have been AID E804007F00070302 |
// AID E80704007F00070304 defined by "BSI TR-03109-2" was intended to represent 0.4.0.127.0.7.3.4 |
// "more correct" would have been AID E804007F00070304 |
if (substr($rest,0,10) == '04007F0007'/*0.4.0.127.0.7*/) $is_e8_len_oid = true; |
|
// Now conclude |
if (!$is_e8_oid && $is_e8_len_oid) return true/*E8+Length+OID*/; |
if ( $is_e8_oid && !$is_e8_len_oid) return false/*E8+OID*/; |
return null/*ambiguous*/; |
} |
|
function decode_aid($aid,$compact=true) { |
$sout = ''; |
if (strtolower(substr($aid,0,2)) == '0x') $aid = substr($aid,2); |
708,30 → 782,16 |
if ($std_schema == '8') { |
$out[] = array(" $std_schema", "Standard identified by OID"); |
|
// Including the DER Encoding "Length" is not defined by ISO but used illegally |
// by German BSI (beside the fact that ISO never allowed anyone else to use E8-AIDs outside |
// of OID arc 1.0), |
// e.g. 0xE80704007F00070302 defined by "BSI TR-03110" was intended to represent 0.4.0.127.0.7.3.2 |
// "more correct" would have been 0xE804007F00070302 |
// 0xE80704007F00070304 defined by "BSI TR-03109-2" was intended to represent 0.4.0.127.0.7.3.4 |
// "more correct" would have been 0xE804007F00070304 |
$include_der_length_roots = array( |
'04007F0007' /* bsi-de (0.4.0.127.0.7) */ |
); |
$include_der_length = false; |
foreach ($include_der_length_roots as $include_der_length_root) { |
$der_length_hex = null; |
$der_length_dec = null; |
if (substr($aid,4,strlen($include_der_length_root)) == $include_der_length_root) { |
// Start: Try to find out if it is E8+Length+OID (inofficial/illegal) or E8+OID (ISO) |
$len_usage = _aid_e8_length_usage($aid); |
$include_der_length = true; // In case it is ambiguous , let's say it is E8+Length+OID |
// Note that these ambiguous are rare and will only happen inside the root OID 0 |
if ($len_usage === true) $include_der_length = true; |
if ($len_usage === false) $include_der_length = false; |
if ($include_der_length) { |
// Case E8+Length+OID (inofficial/illegal) |
$der_length_hex = substr($aid,2,2); |
$der_length_dec = hexdec($der_length_hex); |
if ($der_length_dec <= 14) { |
$include_der_length = true; |
break; |
} |
} |
} |
if ($include_der_length) { |
$out[] = array(" $der_length_hex", "DER encoding length (illegal usage not defined by ISO)"); |
$pure_der = substr($aid,4); |
$indent = 4; |
739,15 → 799,23 |
$e8_min = $der_length_dec; |
$e8_max = $der_length_dec; |
} else { |
// Case E8+OID (defined by ISO, but only for their 1.0 OID) |
$pure_der = substr($aid,2); |
$indent = 2; |
if (substr($aid,2,2) == '28') { // '28' = OID 1.0 (ISO Standard) |
// ISO Standards (OID 1.0) will only have 1 or 2 numbers. (Number 1 is the standard, and number 2 |
// is the part in case of a multi-part standard). |
$e8_minmax_measure = 'ARC'; |
$e8_min = 3; // 1.0.aaaa (ISO AAAA) |
$e8_max = 4; // 1.0.aaaa.b (ISO AAAA-B) |
} else { |
// This is the inofficial usage of E8+OID |
$e8_minmax_measure = 'ARC'; |
$e8_min = 2; // At least 2 arcs (OID x.y) |
$e8_max = -1; // no limit |
} |
// --- End of BSI compatibility hack --- |
} |
// End: Try to find out if it is E8+Length+OID (inofficial/illegal) or E8+OID (ISO) |
|
try { |
$interpretations = _aid_e8_interpretations($pure_der,$e8_minmax_measure,$e8_min,$e8_max); |