Subversion Repositories php_utils

Compare Revisions

Regard whitespace Rev 45 → Rev 46

/trunk/aid_decoder.inc.php
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);