Update certutils
This commit is contained in:
@@ -23,11 +23,11 @@
|
|||||||
<member priority="0">
|
<member priority="0">
|
||||||
<callManager>
|
<callManager>
|
||||||
<name>moviebox</name>
|
<name>moviebox</name>
|
||||||
<ipv6Addr>2001:471:2f25:3ce::466</ipv6Addr>
|
<ipv6Addr>2001:471:2f25:3ce::3</ipv6Addr>
|
||||||
<ports>
|
<ports>
|
||||||
<ethernetPhonePort>2000</ethernetPhonePort>
|
<ethernetPhonePort>2000</ethernetPhonePort>
|
||||||
</ports>
|
</ports>
|
||||||
<processNodeName>192.168.0.3</processNodeName>
|
<processNodeName>192.168.187.3</processNodeName>
|
||||||
</callManager>
|
</callManager>
|
||||||
</member>
|
</member>
|
||||||
<member priority="1">
|
<member priority="1">
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
<ports>
|
<ports>
|
||||||
<ethernetPhonePort>2000</ethernetPhonePort>
|
<ethernetPhonePort>2000</ethernetPhonePort>
|
||||||
</ports>
|
</ports>
|
||||||
<processNodeName>192.168.0.2</processNodeName>
|
<processNodeName>192.168.187.3</processNodeName>
|
||||||
</callManager>
|
</callManager>
|
||||||
</member>
|
</member>
|
||||||
</members>
|
</members>
|
||||||
@@ -68,6 +68,7 @@
|
|||||||
<loadInformation00436 model="Cisco IP Phone 7965">SCCP45.9-3-1SR1-1S</loadInformation00436>
|
<loadInformation00436 model="Cisco IP Phone 7965">SCCP45.9-3-1SR1-1S</loadInformation00436>
|
||||||
<loadInformation00437 model="Cisco IP Phone 7975">SCCP75.9-4-2SR3-1S</loadInformation00437>
|
<loadInformation00437 model="Cisco IP Phone 7975">SCCP75.9-4-2SR3-1S</loadInformation00437>
|
||||||
<loadInformation00495 model="Cisco IP Phone 6921">SCCP69xx.9-4-1-3SR3</loadInformation00495>
|
<loadInformation00495 model="Cisco IP Phone 6921">SCCP69xx.9-4-1-3SR3</loadInformation00495>
|
||||||
|
<!--<loadInformation00495 model="Cisco IP Phone 6921">SCCP69xx.9-3-1-3</loadInformation00495>-->
|
||||||
<loadInformation00496 model="Cisco IP Phone 6941">SCCP69xx.9-3-1-3</loadInformation00496>
|
<loadInformation00496 model="Cisco IP Phone 6941">SCCP69xx.9-3-1-3</loadInformation00496>
|
||||||
<loadInformation00497 model="Cisco IP Phone 6961">SCCP69xx.9-3-1-3</loadInformation00497>
|
<loadInformation00497 model="Cisco IP Phone 6961">SCCP69xx.9-3-1-3</loadInformation00497>
|
||||||
<loadInformation00547 model="Cisco IP Phone 6901">SCCP6901.9-2-1-a</loadInformation00547>
|
<loadInformation00547 model="Cisco IP Phone 6901">SCCP6901.9-2-1-a</loadInformation00547>
|
||||||
@@ -113,9 +114,9 @@
|
|||||||
</commonProfile>
|
</commonProfile>
|
||||||
|
|
||||||
<vendorConfig>
|
<vendorConfig>
|
||||||
<logServer>192.168.0.3</logServer>
|
<logServer>192.168.178.3</logServer>
|
||||||
<syslogServer>192.168.0.3</syslogServer>
|
<syslogServer>192.168.178.3</syslogServer>
|
||||||
<debugServer>192.168.0.3</debugServer>
|
<debugServer>192.168.178.3</debugServer>
|
||||||
<debugLevel>3</debugLevel>
|
<debugLevel>3</debugLevel>
|
||||||
<disableSpeaker>false</disableSpeaker>
|
<disableSpeaker>false</disableSpeaker>
|
||||||
<disableSpeakerAndHeadset>false</disableSpeakerAndHeadset>
|
<disableSpeakerAndHeadset>false</disableSpeakerAndHeadset>
|
||||||
@@ -223,12 +224,12 @@
|
|||||||
<userId>9999</userId>
|
<userId>9999</userId>
|
||||||
|
|
||||||
<!-- Begin URL's -->
|
<!-- Begin URL's -->
|
||||||
<idleURL>http://192.168.0.3/idle.php</idleURL>
|
<idleURL>http://192.168.178.3/idle.php</idleURL>
|
||||||
<authenticationURL>http://192.168.0.3/authenticate.php</authenticationURL>
|
<authenticationURL>http://192.168.178.3/authenticate.php</authenticationURL>
|
||||||
<informationURL>http://192.168.0.3/cisco_menu/help/help.php</informationURL>
|
<informationURL>http://192.168.178.3/cisco_menu/help/help.php</informationURL>
|
||||||
<messagesURL/>
|
<messagesURL/>
|
||||||
<proxyServerURL/>
|
<proxyServerURL/>
|
||||||
<servicesURL>http://192.168.0.3/tests.xml</servicesURL>
|
<servicesURL>http://192.168.178.3/tests.xml</servicesURL>
|
||||||
<directoryURL>http://192.168.0.3/cisco_menu/directory/menu.php</directoryURL>
|
<directoryURL>http://192.168.178.3/cisco_menu/directory/menu.php</directoryURL>
|
||||||
<!-- End URL's -->
|
<!-- End URL's -->
|
||||||
</Default>
|
</Default>
|
||||||
|
@@ -12,8 +12,8 @@ sub new {
|
|||||||
my $class = shift;
|
my $class = shift;
|
||||||
|
|
||||||
my $self = {
|
my $self = {
|
||||||
content => undef,
|
content => undef,
|
||||||
index => 0
|
index => 0
|
||||||
};
|
};
|
||||||
|
|
||||||
return bless ($self, $class);
|
return bless ($self, $class);
|
||||||
|
@@ -17,12 +17,12 @@ sub new {
|
|||||||
croak 'No content' unless (length $content);
|
croak 'No content' unless (length $content);
|
||||||
|
|
||||||
my $self = {
|
my $self = {
|
||||||
content => $content,
|
content => $content,
|
||||||
content_length => length $content,
|
content_length => length $content,
|
||||||
index => 0,
|
index => 0,
|
||||||
tag => undef,
|
tag => undef,
|
||||||
length => 0,
|
length => 0,
|
||||||
value => undef
|
value => undef
|
||||||
};
|
};
|
||||||
|
|
||||||
return bless ($self, $class);
|
return bless ($self, $class);
|
||||||
|
@@ -8,15 +8,14 @@ use parent qw/Exporter/;
|
|||||||
our $VERSION = '1.0';
|
our $VERSION = '1.0';
|
||||||
|
|
||||||
our %EXPORT_TAGS = (header => [qw/HEADER_VERSION HEADER_LENGTH HEADER_SIGNER_ID HEADER_SIGNER_NAME HEADER_SERIAL_NUMBER
|
our %EXPORT_TAGS = (header => [qw/HEADER_VERSION HEADER_LENGTH HEADER_SIGNER_ID HEADER_SIGNER_NAME HEADER_SERIAL_NUMBER
|
||||||
HEADER_CA_NAME HEADER_SIGNATURE_INFO HEADER_DIGEST_ALGORITHM
|
HEADER_CA_NAME HEADER_SIGNATURE_INFO HEADER_DIGEST_ALGORITHM
|
||||||
HEADER_SIGNATURE_ALGORITHM_INFO HEADER_SIGNATURE_ALGORITHM HEADER_SIGNATURE_MODULUS
|
HEADER_SIGNATURE_ALGORITHM_INFO HEADER_SIGNATURE_ALGORITHM HEADER_SIGNATURE_MODULUS
|
||||||
HEADER_SIGNATURE HEADER_PADDING HEADER_FILENAME HEADER_TIMESTAMP/],
|
HEADER_SIGNATURE HEADER_PADDING HEADER_FILENAME HEADER_TIMESTAMP/],
|
||||||
record => [qw/RECORD_LENGTH RECORD_DNS_NAME RECORD_SUBJECT_NAME RECORD_FUNCTION RECORD_ISSUER_NAME
|
record => [qw/RECORD_LENGTH RECORD_DNS_NAME RECORD_SUBJECT_NAME RECORD_FUNCTION RECORD_ISSUER_NAME
|
||||||
RECORD_SERIAL_NUMBER RECORD_PUBLIC_KEY RECORD_SIGNATURE RECORD_CERTIFICATE
|
RECORD_SERIAL_NUMBER RECORD_PUBLIC_KEY RECORD_SIGNATURE RECORD_CERTIFICATE
|
||||||
RECORD_IP_ADDRESS RECORD_CERTIFICATE_HASH RECORD_HASH_ALGORITHM/],
|
RECORD_IP_ADDRESS RECORD_CERTIFICATE_HASH RECORD_HASH_ALGORITHM/],
|
||||||
digest => [qw/DIGEST_SHA1 DIGEST_SHA256 DIGEST_SHA384 DIGEST_SHA512/],
|
digest => [qw/DIGEST_SHA1 DIGEST_SHA256 DIGEST_SHA384 DIGEST_SHA512/],
|
||||||
function => [qw/FUNCTION_SAST FUNCTION_CCM FUNCTION_CCM_TFTP FUNCTION_TFTP FUNCTION_CAPF FUNCTION_SRST
|
function => [qw/FUNCTION_SAST FUNCTION_CCM FUNCTION_CCM_TFTP FUNCTION_TFTP FUNCTION_HTTPS/]);
|
||||||
FUNCTION_HTTPS FUNCTION_TVS/]);
|
|
||||||
|
|
||||||
our @EXPORT_OK = (@{$EXPORT_TAGS{header}}, @{$EXPORT_TAGS{record}}, @{$EXPORT_TAGS{digest}}, @{$EXPORT_TAGS{function}});
|
our @EXPORT_OK = (@{$EXPORT_TAGS{header}}, @{$EXPORT_TAGS{record}}, @{$EXPORT_TAGS{digest}}, @{$EXPORT_TAGS{function}});
|
||||||
|
|
||||||
|
@@ -30,7 +30,14 @@ eval {
|
|||||||
my $digest = Digest->new ('SHA-1');
|
my $digest = Digest->new ('SHA-1');
|
||||||
|
|
||||||
$digest->add ($x509->as_string (FORMAT_ASN1));
|
$digest->add ($x509->as_string (FORMAT_ASN1));
|
||||||
print $digest->b64digest, "\n";
|
$content = $digest->b64digest;
|
||||||
|
|
||||||
|
# Digest must be padded to a 4 byte length
|
||||||
|
while (length ($content) % 4) {
|
||||||
|
$content .= '=';
|
||||||
|
}
|
||||||
|
|
||||||
|
print $content, "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
if (length $EVAL_ERROR) {
|
if (length $EVAL_ERROR) {
|
||||||
|
@@ -21,98 +21,98 @@ while true; do
|
|||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-C|--common)
|
-C|--common)
|
||||||
COMMON_NAME="$2"
|
COMMON_NAME="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-O|--organization)
|
-O|--organization)
|
||||||
ORGANIZATION="$2"
|
ORGANIZATION="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-l|--locality)
|
-l|--locality)
|
||||||
LOCALITY="$2"
|
LOCALITY="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-s|--state)
|
-s|--state)
|
||||||
STATE="$2"
|
STATE="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-t|--country)
|
-t|--country)
|
||||||
COUNTRY="$2"
|
COUNTRY="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-e|--email)
|
-e|--email)
|
||||||
EMAIL_ADDRESS="$2"
|
EMAIL_ADDRESS="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-b|--bits)
|
-b|--bits)
|
||||||
BITS="$2"
|
BITS="$2"
|
||||||
shift 2
|
shift 2
|
||||||
|
|
||||||
if [[ ! $BITS =~ ^[0-9]+$ || $BITS -lt 512 || $BITS -gt 4096 ]]; then
|
if [[ ! $BITS =~ ^[0-9]+$ || $BITS -lt 512 || $BITS -gt 4096 ]]; then
|
||||||
echo "Invalid --bits \`$BITS'"
|
echo "Invalid --bits \`$BITS'"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
-y|--years)
|
-y|--years)
|
||||||
YEARS="$2"
|
YEARS="$2"
|
||||||
shift 2
|
shift 2
|
||||||
|
|
||||||
if [[ ! $YEARS =~ ^[0-9]+$ || $YEARS -lt 1 ]]; then
|
if [[ ! $YEARS =~ ^[0-9]+$ || $YEARS -lt 1 ]]; then
|
||||||
echo "Invalid --years \`$YEARS'"
|
echo "Invalid --years \`$YEARS'"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
-d|--digest)
|
-d|--digest)
|
||||||
DIGEST="${2,,[a-z]}"
|
DIGEST="${2,,[a-z]}"
|
||||||
shift 2
|
shift 2
|
||||||
|
|
||||||
if [[ $DIGEST != +(sha1|sha256) ]]; then
|
if [[ $DIGEST != +(sha1|sha256) ]]; then
|
||||||
echo "Invaid --digest \`$DIGEST'"
|
echo "Invaid --digest \`$DIGEST'"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
-o|--output)
|
-o|--output)
|
||||||
OUTPUT_FILE="$2"
|
OUTPUT_FILE="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-c|--cacert)
|
-c|--cacert)
|
||||||
CA_CERT="$2"
|
CA_CERT="$2"
|
||||||
shift 2
|
shift 2
|
||||||
|
|
||||||
if ! test -f "$CA_CERT"; then
|
if ! test -f "$CA_CERT"; then
|
||||||
echo "CA certificate does not exist"
|
echo "CA certificate does not exist"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
-n|--newca)
|
-n|--newca)
|
||||||
NEW_CA=true
|
NEW_CA=true
|
||||||
shift 1
|
shift 1
|
||||||
;;
|
;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
echo "Usage: ${0##*/} [OPTIONS]"
|
echo "Usage: ${0##*/} [OPTIONS]"
|
||||||
echo "Generate and sign X509 certificates"
|
echo "Generate and sign X509 certificates"
|
||||||
echo ""
|
echo ""
|
||||||
echo " -C --common <name> common name"
|
echo " -C --common <name> common name"
|
||||||
echo " -O --organization <name> organization"
|
echo " -O --organization <name> organization"
|
||||||
echo " -l --locality <name> locality"
|
echo " -l --locality <name> locality"
|
||||||
echo " -s --state <name> state"
|
echo " -s --state <name> state"
|
||||||
echo " -t --country <name> country"
|
echo " -t --country <name> country"
|
||||||
echo " -e --email <address> email address"
|
echo " -e --email <address> email address"
|
||||||
echo " -n --bits <size> RSA key size (default 2048)"
|
echo " -n --bits <size> RSA key size (default 2048)"
|
||||||
echo " -y --years <number> number of years to sign the certificate (default 10)"
|
echo " -y --years <number> number of years to sign the certificate (default 10)"
|
||||||
echo " -d --digest <name> message digest to use (sha1, sha256)"
|
echo " -d --digest <name> message digest to use (sha1, sha256)"
|
||||||
echo " -o --output output file"
|
echo " -o --output output file"
|
||||||
echo " -c --cacert CA certificate to use for signing"
|
echo " -c --cacert CA certificate to use for signing"
|
||||||
echo " -n --newca generate a CA certificate instead"
|
echo " -n --newca generate a CA certificate instead"
|
||||||
echo " -h --help print this help and exit"
|
echo " -h --help print this help and exit"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
shift 1
|
shift 1
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -208,23 +208,23 @@ fi
|
|||||||
|
|
||||||
if $NEW_CA; then
|
if $NEW_CA; then
|
||||||
if ! openssl ca -config $TEMP_DIR/openssl.cnf -selfsign -batch -startdate $START_DATE -enddate $END_DATE -md $DIGEST \
|
if ! openssl ca -config $TEMP_DIR/openssl.cnf -selfsign -batch -startdate $START_DATE -enddate $END_DATE -md $DIGEST \
|
||||||
-extensions req_extensions -keyfile $TEMP_DIR/key.pem -notext -in $TEMP_DIR/req.pem -out $TEMP_DIR/crt.pem 2> /dev/null; then
|
-extensions req_extensions -keyfile $TEMP_DIR/key.pem -notext -in $TEMP_DIR/req.pem -out $TEMP_DIR/crt.pem 2> /dev/null; then
|
||||||
echo "Error while signing CA certificate"
|
echo "Error while signing CA certificate"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat $TEMP_DIR/key.pem $TEMP_DIR/crt.pem > $OUTPUT_FILE
|
cat $TEMP_DIR/key.pem $TEMP_DIR/crt.pem > $OUTPUT_FILE
|
||||||
echo "New CA certificate created. Certificate and private-key saved in $OUTPUT_FILE"
|
echo "New CA certificate created. Certificate and private-key saved in $OUTPUT_FILE"
|
||||||
else
|
else
|
||||||
if test -z "$CA_CERT"; then
|
if test -z "$CA_CERT"; then
|
||||||
echo "No CA certificate specified"
|
echo "No CA certificate specified"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! openssl ca -config $TEMP_DIR/openssl.cnf -batch -startdate $START_DATE -enddate $END_DATE -md $DIGEST -extensions ca_extensions \
|
if ! openssl ca -config $TEMP_DIR/openssl.cnf -batch -startdate $START_DATE -enddate $END_DATE -md $DIGEST -extensions ca_extensions \
|
||||||
-keyfile $CA_CERT -cert $CA_CERT -notext -in $TEMP_DIR/req.pem -out $TEMP_DIR/crt.pem 2>/dev/null; then
|
-keyfile $CA_CERT -cert $CA_CERT -notext -in $TEMP_DIR/req.pem -out $TEMP_DIR/crt.pem 2>/dev/null; then
|
||||||
echo "Error while signing certificate"
|
echo "Error while signing certificate"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat $TEMP_DIR/key.pem $TEMP_DIR/crt.pem > $OUTPUT_FILE
|
cat $TEMP_DIR/key.pem $TEMP_DIR/crt.pem > $OUTPUT_FILE
|
||||||
|
@@ -29,7 +29,7 @@ sub parse_sgn {
|
|||||||
my ($file, $content);
|
my ($file, $content);
|
||||||
|
|
||||||
unless ($file = IO::File->new ($certificate_file, '<:raw')) {
|
unless ($file = IO::File->new ($certificate_file, '<:raw')) {
|
||||||
die 'Unable to read ' . $certificate_file . ': ' . $OS_ERROR;
|
die 'Unable to read ' . $certificate_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
||||||
@@ -39,7 +39,7 @@ sub parse_sgn {
|
|||||||
die 'Unable to load certificate' unless ($x509);
|
die 'Unable to load certificate' unless ($x509);
|
||||||
|
|
||||||
unless ($file = IO::File->new ($sgn_file, '<:raw')) {
|
unless ($file = IO::File->new ($sgn_file, '<:raw')) {
|
||||||
die 'Unable to read ' . $sgn_file . ': ' . $OS_ERROR;
|
die 'Unable to read ' . $sgn_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
||||||
@@ -59,88 +59,88 @@ sub parse_sgn {
|
|||||||
my $header_length = unpack ('S>', $parser->next_value);
|
my $header_length = unpack ('S>', $parser->next_value);
|
||||||
|
|
||||||
print 'Version: ', $version, "\n",
|
print 'Version: ', $version, "\n",
|
||||||
'Header Length: ', $header_length, ' bytes', "\n";
|
'Header Length: ', $header_length, ' bytes', "\n";
|
||||||
|
|
||||||
my ($header_digest_algorithm, $header_signature_index, $header_signature_length);
|
my ($header_digest_algorithm, $header_signature_index, $header_signature_length);
|
||||||
|
|
||||||
while ($parser->index < $header_length) {
|
while ($parser->index < $header_length) {
|
||||||
$parser->next_tag;
|
$parser->next_tag;
|
||||||
next if ($parser->tag == HEADER_PADDING);
|
next if ($parser->tag == HEADER_PADDING);
|
||||||
$parser->next_length;
|
$parser->next_length;
|
||||||
|
|
||||||
if ($parser->tag == HEADER_SIGNER_ID) {
|
if ($parser->tag == HEADER_SIGNER_ID) {
|
||||||
my $signer_id = $parser->length;
|
my $signer_id = $parser->length;
|
||||||
|
|
||||||
print 'Signer ID: ', $signer_id, "\n";
|
print 'Signer ID: ', $signer_id, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNER_NAME) {
|
} elsif ($parser->tag == HEADER_SIGNER_NAME) {
|
||||||
my $signer_name = unpack ('Z*', $parser->next_value);
|
my $signer_name = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'Signer Name: ', $signer_name, "\n";
|
print 'Signer Name: ', $signer_name, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SERIAL_NUMBER) {
|
} elsif ($parser->tag == HEADER_SERIAL_NUMBER) {
|
||||||
my $serial_number = uc unpack ('H*', $parser->next_value);
|
my $serial_number = uc unpack ('H*', $parser->next_value);
|
||||||
|
|
||||||
print 'Serial Number: ', join (':', $serial_number =~ m/(..)/g), "\n";
|
print 'Serial Number: ', join (':', $serial_number =~ m/(..)/g), "\n";
|
||||||
} elsif ($parser->tag == HEADER_CA_NAME) {
|
} elsif ($parser->tag == HEADER_CA_NAME) {
|
||||||
my $ca_name = unpack ('Z*', $parser->next_value);
|
my $ca_name = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'CA Name: ', $ca_name, "\n";
|
print 'CA Name: ', $ca_name, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE_INFO) {
|
} elsif ($parser->tag == HEADER_SIGNATURE_INFO) {
|
||||||
my $signature_info = $parser->length;
|
my $signature_info = $parser->length;
|
||||||
|
|
||||||
print 'Signature Info: ', $signature_info, "\n";
|
print 'Signature Info: ', $signature_info, "\n";
|
||||||
} elsif ($parser->tag == HEADER_DIGEST_ALGORITHM) {
|
} elsif ($parser->tag == HEADER_DIGEST_ALGORITHM) {
|
||||||
die 'Invalid digest_algorithm length: ' . $parser->length if ($parser->length != 1);
|
die 'Invalid digest_algorithm length: ' . $parser->length if ($parser->length != 1);
|
||||||
|
|
||||||
my $digest_algorithm = unpack ('C', $parser->next_value);
|
my $digest_algorithm = unpack ('C', $parser->next_value);
|
||||||
|
|
||||||
$header_digest_algorithm = $digest_algorithm;
|
$header_digest_algorithm = $digest_algorithm;
|
||||||
|
|
||||||
print 'Digest Algorithm: ';
|
print 'Digest Algorithm: ';
|
||||||
|
|
||||||
if ($digest_algorithm == DIGEST_SHA1) {
|
if ($digest_algorithm == DIGEST_SHA1) {
|
||||||
print 'SHA1';
|
print 'SHA1';
|
||||||
} elsif ($digest_algorithm == DIGEST_SHA256) {
|
} elsif ($digest_algorithm == DIGEST_SHA256) {
|
||||||
print 'SHA256';
|
print 'SHA256';
|
||||||
}
|
}
|
||||||
|
|
||||||
print "\n";
|
print "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE_ALGORITHM_INFO) {
|
} elsif ($parser->tag == HEADER_SIGNATURE_ALGORITHM_INFO) {
|
||||||
my $signature_algorithm_info = $parser->length;
|
my $signature_algorithm_info = $parser->length;
|
||||||
|
|
||||||
print 'Signature Algorithm Info: ', $signature_algorithm_info, "\n";
|
print 'Signature Algorithm Info: ', $signature_algorithm_info, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE_ALGORITHM) {
|
} elsif ($parser->tag == HEADER_SIGNATURE_ALGORITHM) {
|
||||||
die 'Invalid signature_algorithm length: ' . $parser->length if ($parser->length != 1);
|
die 'Invalid signature_algorithm length: ' . $parser->length if ($parser->length != 1);
|
||||||
|
|
||||||
my $signature_algorithm = unpack ('C', $parser->next_value);
|
my $signature_algorithm = unpack ('C', $parser->next_value);
|
||||||
|
|
||||||
print 'Signature Algorithm: ', $signature_algorithm, "\n";
|
print 'Signature Algorithm: ', $signature_algorithm, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE_MODULUS) {
|
} elsif ($parser->tag == HEADER_SIGNATURE_MODULUS) {
|
||||||
die 'Invalid signature_modulus length: ' . $parser->length if ($parser->length != 1);
|
die 'Invalid signature_modulus length: ' . $parser->length if ($parser->length != 1);
|
||||||
|
|
||||||
my $signature_modulus = unpack ('C', $parser->next_value);
|
my $signature_modulus = unpack ('C', $parser->next_value);
|
||||||
|
|
||||||
print 'Signature Modulus: ', $signature_modulus, "\n";
|
print 'Signature Modulus: ', $signature_modulus, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE) {
|
} elsif ($parser->tag == HEADER_SIGNATURE) {
|
||||||
my $signature = $parser->next_value;
|
my $signature = $parser->next_value;
|
||||||
|
|
||||||
# The removal index for the signature
|
# The removal index for the signature
|
||||||
$header_signature_index = $parser->index - $parser->length - 3;
|
$header_signature_index = $parser->index - $parser->length - 3;
|
||||||
$header_signature_length = $parser->length + 3;
|
$header_signature_length = $parser->length + 3;
|
||||||
|
|
||||||
print 'Signature: ', length ($signature), ' bytes', "\n";
|
print 'Signature: ', length ($signature), ' bytes', "\n";
|
||||||
} elsif ($parser->tag == HEADER_FILENAME) {
|
} elsif ($parser->tag == HEADER_FILENAME) {
|
||||||
my $filename = unpack ('Z*', $parser->next_value);
|
my $filename = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'Filename: ', $filename, "\n";
|
print 'Filename: ', $filename, "\n";
|
||||||
} elsif ($parser->tag == HEADER_TIMESTAMP) {
|
} elsif ($parser->tag == HEADER_TIMESTAMP) {
|
||||||
die 'Invalid timestamp length: ' . $parser->length if ($parser->length != 4);
|
die 'Invalid timestamp length: ' . $parser->length if ($parser->length != 4);
|
||||||
|
|
||||||
my $timestamp = unpack ('L>', $parser->next_value);
|
my $timestamp = unpack ('L>', $parser->next_value);
|
||||||
|
|
||||||
print 'Timestamp: ', strftime ('%a, %d %b %Y %H:%M:%S %z', localtime $timestamp), "\n";
|
print 'Timestamp: ', strftime ('%a, %d %b %Y %H:%M:%S %z', localtime $timestamp), "\n";
|
||||||
} else {
|
} else {
|
||||||
die 'Unknown tag: ' . $parser->tag . ' at index: ' . ($parser->index - 3);
|
die 'Unknown tag: ' . $parser->tag . ' at index: ' . ($parser->index - 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print "\n";
|
print "\n";
|
||||||
@@ -152,11 +152,11 @@ sub parse_sgn {
|
|||||||
die 'Unable to parse RSA public key' unless ($rsa);
|
die 'Unable to parse RSA public key' unless ($rsa);
|
||||||
|
|
||||||
if ($header_digest_algorithm == DIGEST_SHA1) {
|
if ($header_digest_algorithm == DIGEST_SHA1) {
|
||||||
$rsa->use_sha1_hash;
|
$rsa->use_sha1_hash;
|
||||||
} elsif ($header_digest_algorithm == DIGEST_SHA256) {
|
} elsif ($header_digest_algorithm == DIGEST_SHA256) {
|
||||||
$rsa->use_sha256_hash;
|
$rsa->use_sha256_hash;
|
||||||
} else {
|
} else {
|
||||||
die 'Unknown header_digest_algorithm: ' . $header_digest_algorithm;
|
die 'Unknown header_digest_algorithm: ' . $header_digest_algorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = $parser->content;
|
$content = $parser->content;
|
||||||
@@ -166,9 +166,9 @@ sub parse_sgn {
|
|||||||
substr ($content, $header_signature_index, $header_signature_length, '');
|
substr ($content, $header_signature_index, $header_signature_length, '');
|
||||||
|
|
||||||
if ($rsa->verify ($content, $signature)) {
|
if ($rsa->verify ($content, $signature)) {
|
||||||
print 'Valid signature', "\n";
|
print 'Valid signature', "\n";
|
||||||
} else {
|
} else {
|
||||||
print 'Invalid signature', "\n";
|
print 'Invalid signature', "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ sub build_sgn {
|
|||||||
my ($file, $content);
|
my ($file, $content);
|
||||||
|
|
||||||
unless ($file = IO::File->new ($certificate_file, '<:raw')) {
|
unless ($file = IO::File->new ($certificate_file, '<:raw')) {
|
||||||
die 'Unable to read ' . $certificate_file . ': ' . $OS_ERROR;
|
die 'Unable to read ' . $certificate_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
||||||
@@ -196,110 +196,110 @@ sub build_sgn {
|
|||||||
die 'Unable to load header private key' unless ($rsa);
|
die 'Unable to load header private key' unless ($rsa);
|
||||||
|
|
||||||
if ($digest_algorithm eq 'SHA1') {
|
if ($digest_algorithm eq 'SHA1') {
|
||||||
$rsa->use_sha1_hash;
|
$rsa->use_sha1_hash;
|
||||||
} elsif ($digest_algorithm eq 'SHA256') {
|
} elsif ($digest_algorithm eq 'SHA256') {
|
||||||
$rsa->use_sha256_hash;
|
$rsa->use_sha256_hash;
|
||||||
} else {
|
} else {
|
||||||
die 'Unknown digest_algorithm: ' . $digest_algorithm;
|
die 'Unknown digest_algorithm: ' . $digest_algorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $builder = TLV::Builder->new;
|
my $builder = TLV::Builder->new;
|
||||||
my $header_signature_index;
|
my $header_signature_index;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
# Header
|
# Header
|
||||||
$builder->next_tag (HEADER_VERSION);
|
$builder->next_tag (HEADER_VERSION);
|
||||||
$builder->next_length (2);
|
$builder->next_length (2);
|
||||||
$builder->next_value (pack ('CC', 1, 2));
|
$builder->next_value (pack ('CC', 1, 2));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_LENGTH);
|
$builder->next_tag (HEADER_LENGTH);
|
||||||
$builder->next_length (2);
|
$builder->next_length (2);
|
||||||
$builder->next_value (pack ('S>', 0));
|
$builder->next_value (pack ('S>', 0));
|
||||||
|
|
||||||
(my $signer_name = $x509->subject) =~ s/, /;/g;
|
(my $signer_name = $x509->subject) =~ s/, /;/g;
|
||||||
(my $ca_name = $x509->issuer) =~ s/, /;/g;
|
(my $ca_name = $x509->issuer) =~ s/, /;/g;
|
||||||
my $serial_number = pack ('H*', $x509->serial);
|
my $serial_number = pack ('H*', $x509->serial);
|
||||||
|
|
||||||
# Combined TLV length for signer_name, serial_number and ca_name
|
# Combined TLV length for signer_name, serial_number and ca_name
|
||||||
my $signer_id = 3 + length ($signer_name) + 1 + 3 + length ($serial_number) + 3 + length ($ca_name) + 1;
|
my $signer_id = 3 + length ($signer_name) + 1 + 3 + length ($serial_number) + 3 + length ($ca_name) + 1;
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNER_ID);
|
$builder->next_tag (HEADER_SIGNER_ID);
|
||||||
$builder->next_length ($signer_id);
|
$builder->next_length ($signer_id);
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNER_NAME);
|
$builder->next_tag (HEADER_SIGNER_NAME);
|
||||||
$builder->next_length (length ($signer_name) + 1);
|
$builder->next_length (length ($signer_name) + 1);
|
||||||
$builder->next_value (pack ('Z*', $signer_name));
|
$builder->next_value (pack ('Z*', $signer_name));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SERIAL_NUMBER);
|
$builder->next_tag (HEADER_SERIAL_NUMBER);
|
||||||
$builder->next_length (length $serial_number);
|
$builder->next_length (length $serial_number);
|
||||||
$builder->next_value ($serial_number);
|
$builder->next_value ($serial_number);
|
||||||
|
|
||||||
$builder->next_tag (HEADER_CA_NAME);
|
$builder->next_tag (HEADER_CA_NAME);
|
||||||
$builder->next_length (length ($ca_name) + 1);
|
$builder->next_length (length ($ca_name) + 1);
|
||||||
$builder->next_value (pack ('Z*', $ca_name));
|
$builder->next_value (pack ('Z*', $ca_name));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNATURE_INFO);
|
$builder->next_tag (HEADER_SIGNATURE_INFO);
|
||||||
$builder->next_length (15); # Unknown
|
$builder->next_length (15); # Unknown
|
||||||
|
|
||||||
$builder->next_tag (HEADER_DIGEST_ALGORITHM);
|
$builder->next_tag (HEADER_DIGEST_ALGORITHM);
|
||||||
$builder->next_length (1);
|
$builder->next_length (1);
|
||||||
$builder->next_value (pack ('C', do {
|
$builder->next_value (pack ('C', do {
|
||||||
if ($digest_algorithm eq 'SHA1') {
|
if ($digest_algorithm eq 'SHA1') {
|
||||||
DIGEST_SHA1;
|
DIGEST_SHA1;
|
||||||
} elsif ($digest_algorithm eq 'SHA256') {
|
} elsif ($digest_algorithm eq 'SHA256') {
|
||||||
DIGEST_SHA256;
|
DIGEST_SHA256;
|
||||||
} else {
|
} else {
|
||||||
die 'Unknown digest algorithm: ' . $digest_algorithm;
|
die 'Unknown digest algorithm: ' . $digest_algorithm;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNATURE_ALGORITHM_INFO);
|
$builder->next_tag (HEADER_SIGNATURE_ALGORITHM_INFO);
|
||||||
$builder->next_length (8); # Unknown
|
$builder->next_length (8); # Unknown
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNATURE_ALGORITHM);
|
$builder->next_tag (HEADER_SIGNATURE_ALGORITHM);
|
||||||
$builder->next_length (1);
|
$builder->next_length (1);
|
||||||
$builder->next_value (pack ('C', 0)); # Unknown
|
$builder->next_value (pack ('C', 0)); # Unknown
|
||||||
|
|
||||||
my $signature_modulus;
|
my $signature_modulus;
|
||||||
|
|
||||||
if ($rsa->size == 64) {
|
if ($rsa->size == 64) {
|
||||||
$signature_modulus = 0;
|
$signature_modulus = 0;
|
||||||
} elsif ($rsa->size == 128) {
|
} elsif ($rsa->size == 128) {
|
||||||
$signature_modulus = 1;
|
$signature_modulus = 1;
|
||||||
} elsif ($rsa->size == 256) {
|
} elsif ($rsa->size == 256) {
|
||||||
$signature_modulus = 2;
|
$signature_modulus = 2;
|
||||||
} elsif ($rsa->size == 512) {
|
} elsif ($rsa->size == 512) {
|
||||||
$signature_modulus = 3;
|
$signature_modulus = 3;
|
||||||
} else {
|
} else {
|
||||||
die 'Unsupported RSA key size: ' . $rsa->size;
|
die 'Unsupported RSA key size: ' . $rsa->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNATURE_MODULUS);
|
$builder->next_tag (HEADER_SIGNATURE_MODULUS);
|
||||||
$builder->next_length (1);
|
$builder->next_length (1);
|
||||||
$builder->next_value (pack ('C', $signature_modulus));
|
$builder->next_value (pack ('C', $signature_modulus));
|
||||||
|
|
||||||
# The insertion index of the signature
|
# The insertion index of the signature
|
||||||
$header_signature_index = $builder->index;
|
$header_signature_index = $builder->index;
|
||||||
|
|
||||||
$builder->next_tag (HEADER_FILENAME);
|
$builder->next_tag (HEADER_FILENAME);
|
||||||
$builder->next_length (length ($filename) + 1);
|
$builder->next_length (length ($filename) + 1);
|
||||||
$builder->next_value (pack ('Z*', $filename));
|
$builder->next_value (pack ('Z*', $filename));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_TIMESTAMP);
|
$builder->next_tag (HEADER_TIMESTAMP);
|
||||||
$builder->next_length (4);
|
$builder->next_length (4);
|
||||||
$builder->next_value (pack ('L>', time));
|
$builder->next_value (pack ('L>', time));
|
||||||
|
|
||||||
# Header must be padded to 32-bit boundary
|
# Header must be padded to 32-bit boundary
|
||||||
while (($builder->index + 3 + $rsa->size) % 4) {
|
while (($builder->index + 3 + $rsa->size) % 4) {
|
||||||
$builder->next_tag (HEADER_PADDING);
|
$builder->next_tag (HEADER_PADDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Signed content includes the length of the signature block
|
# Signed content includes the length of the signature block
|
||||||
$builder->length (8, $builder->index + 3 + $rsa->size);
|
$builder->length (8, $builder->index + 3 + $rsa->size);
|
||||||
};
|
};
|
||||||
|
|
||||||
unless ($file = IO::File->new ($content_file, '<:raw')) {
|
unless ($file = IO::File->new ($content_file, '<:raw')) {
|
||||||
die 'Unable to read ' . $content_file . ': ' . $OS_ERROR;
|
die 'Unable to read ' . $content_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
||||||
@@ -316,7 +316,7 @@ sub build_sgn {
|
|||||||
my $sgn_file = $content_file . '.sgn';
|
my $sgn_file = $content_file . '.sgn';
|
||||||
|
|
||||||
unless ($file = IO::File->new ($sgn_file, '>:raw')) {
|
unless ($file = IO::File->new ($sgn_file, '>:raw')) {
|
||||||
die 'Unable to write ' . $sgn_file . ': ' . $OS_ERROR;
|
die 'Unable to write ' . $sgn_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$file->print ($content);
|
$file->print ($content);
|
||||||
@@ -333,44 +333,44 @@ eval {
|
|||||||
$getopt->configure (qw/no_ignore_case/);
|
$getopt->configure (qw/no_ignore_case/);
|
||||||
|
|
||||||
unless ($getopt->getoptions ('p|parse' => sub {shift; $mode = 'parse'},
|
unless ($getopt->getoptions ('p|parse' => sub {shift; $mode = 'parse'},
|
||||||
'b|build' => sub {shift; $mode = 'build'},
|
'b|build' => sub {shift; $mode = 'build'},
|
||||||
'c|certificate=s' => sub {shift; $certificate_file = shift},
|
'c|certificate=s' => sub {shift; $certificate_file = shift},
|
||||||
'd|digest=s' => sub {shift; $digest_algorithm = uc shift},
|
'd|digest=s' => sub {shift; $digest_algorithm = uc shift},
|
||||||
'F|filename=s' => sub {shift; $filename = shift},
|
'F|filename=s' => sub {shift; $filename = shift},
|
||||||
'h|help' => sub {shift; $show_help = shift})) {
|
'h|help' => sub {shift; $show_help = shift})) {
|
||||||
die 'Error parsing options';
|
die 'Error parsing options';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($show_help) {
|
if ($show_help) {
|
||||||
print 'Usage: ', basename ($PROGRAM_NAME), ' <FILE> [OPTIONS]', "\n",
|
print 'Usage: ', basename ($PROGRAM_NAME), ' <FILE> [OPTIONS]', "\n",
|
||||||
'Parse or build a .sgn file', "\n",
|
'Parse or build a .sgn file', "\n",
|
||||||
"\n",
|
"\n",
|
||||||
' -p --parse parse a .sgn file', "\n",
|
' -p --parse parse a .sgn file', "\n",
|
||||||
' -b --build build a .sgn file', "\n",
|
' -b --build build a .sgn file', "\n",
|
||||||
' -c --certificate <file> certificate to use for verifying or signing', "\n",
|
' -c --certificate <file> certificate to use for verifying or signing', "\n",
|
||||||
' -d --digest <name> signature digest (sha1, sha256)', "\n",
|
' -d --digest <name> signature digest (sha1, sha256)', "\n",
|
||||||
' -F --filename <name> header filename in built .sgn file (optional)', "\n",
|
' -F --filename <name> header filename in built .sgn file (optional)', "\n",
|
||||||
' -h --help print this help and exit', "\n",
|
' -h --help print this help and exit', "\n",
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
die 'No verifying/signing certificate file specified' unless (length $certificate_file);
|
die 'No verifying/signing certificate file specified' unless (length $certificate_file);
|
||||||
|
|
||||||
if ($mode eq 'parse') {
|
if ($mode eq 'parse') {
|
||||||
die 'No .sgn file specified' unless (length ($sgn_file = shift));
|
die 'No .sgn file specified' unless (length ($sgn_file = shift));
|
||||||
|
|
||||||
parse_sgn ($sgn_file, $certificate_file);
|
parse_sgn ($sgn_file, $certificate_file);
|
||||||
} elsif ($mode eq 'build') {
|
} elsif ($mode eq 'build') {
|
||||||
die 'No file specified' unless (length ($content_file = shift));
|
die 'No file specified' unless (length ($content_file = shift));
|
||||||
|
|
||||||
$digest_algorithm = 'SHA1' unless (length $digest_algorithm);
|
$digest_algorithm = 'SHA1' unless (length $digest_algorithm);
|
||||||
$filename = basename ($content_file) . '.sgn' unless (length $filename);
|
$filename = basename ($content_file) . '.sgn' unless (length $filename);
|
||||||
|
|
||||||
build_sgn ($content_file, $certificate_file, $digest_algorithm, $filename);
|
build_sgn ($content_file, $certificate_file, $digest_algorithm, $filename);
|
||||||
} else {
|
} else {
|
||||||
die 'No mode specified';
|
die 'No mode specified, choose ether --build, --parse or --help for available options';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -18,11 +18,11 @@ eval {
|
|||||||
my $input_file;
|
my $input_file;
|
||||||
|
|
||||||
unless ($input_file = IO::File->new ($sgn_file, '<:raw')) {
|
unless ($input_file = IO::File->new ($sgn_file, '<:raw')) {
|
||||||
die 'Unable to read ' .$sgn_file . ' :' . $OS_ERROR;
|
die 'Unable to read ' .$sgn_file . ' :' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $content;
|
my $content;
|
||||||
|
|
||||||
die 'Unable to read header: ' . $OS_ERROR if ($input_file->read ($content, 10) != 10);
|
die 'Unable to read header: ' . $OS_ERROR if ($input_file->read ($content, 10) != 10);
|
||||||
|
|
||||||
my ($tag, $length, $index);
|
my ($tag, $length, $index);
|
||||||
@@ -52,13 +52,13 @@ eval {
|
|||||||
my $output_file;
|
my $output_file;
|
||||||
|
|
||||||
unless ($output_file = IO::File->new ($content_file, '>:raw')) {
|
unless ($output_file = IO::File->new ($content_file, '>:raw')) {
|
||||||
die 'Unable to write ' . $content_file . ': ' . $OS_ERROR;
|
die 'Unable to write ' . $content_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ($input_file->read ($content, 4096)) {
|
while ($input_file->read ($content, 4096)) {
|
||||||
$output_file->write ($content);
|
$output_file->write ($content);
|
||||||
}
|
}
|
||||||
|
|
||||||
$input_file->close;
|
$input_file->close;
|
||||||
$output_file->close;
|
$output_file->close;
|
||||||
};
|
};
|
||||||
|
@@ -26,7 +26,7 @@ sub parse_tlv {
|
|||||||
my ($file, $content);
|
my ($file, $content);
|
||||||
|
|
||||||
unless ($file = IO::File->new ($tlv_file, '<:raw')) {
|
unless ($file = IO::File->new ($tlv_file, '<:raw')) {
|
||||||
die 'Unable to read ' . $tlv_file . ': ' . $OS_ERROR;
|
die 'Unable to read ' . $tlv_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
||||||
@@ -46,91 +46,91 @@ sub parse_tlv {
|
|||||||
my $header_length = unpack ('S>', $parser->next_value);
|
my $header_length = unpack ('S>', $parser->next_value);
|
||||||
|
|
||||||
print 'Version: ', $version, "\n",
|
print 'Version: ', $version, "\n",
|
||||||
'Header Length: ', $header_length, ' bytes', "\n";
|
'Header Length: ', $header_length, ' bytes', "\n";
|
||||||
|
|
||||||
my ($header_serial_number, $header_digest_algorithm, $header_signature_index, $header_signature_length);
|
my ($header_serial_number, $header_digest_algorithm, $header_signature_index, $header_signature_length);
|
||||||
|
|
||||||
while ($parser->index < $header_length) {
|
while ($parser->index < $header_length) {
|
||||||
$parser->next_tag;
|
$parser->next_tag;
|
||||||
next if ($parser->tag == HEADER_PADDING);
|
next if ($parser->tag == HEADER_PADDING);
|
||||||
$parser->next_length;
|
$parser->next_length;
|
||||||
|
|
||||||
if ($parser->tag == HEADER_SIGNER_ID) {
|
if ($parser->tag == HEADER_SIGNER_ID) {
|
||||||
my $signer_id = $parser->length;
|
my $signer_id = $parser->length;
|
||||||
|
|
||||||
print 'Signer ID: ', $signer_id, "\n";
|
print 'Signer ID: ', $signer_id, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNER_NAME) {
|
} elsif ($parser->tag == HEADER_SIGNER_NAME) {
|
||||||
my $signer_name = unpack ('Z*', $parser->next_value);
|
my $signer_name = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'Signer Name: ', $signer_name, "\n";
|
print 'Signer Name: ', $signer_name, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SERIAL_NUMBER) {
|
} elsif ($parser->tag == HEADER_SERIAL_NUMBER) {
|
||||||
my $serial_number = uc unpack ('H*', $parser->next_value);
|
my $serial_number = uc unpack ('H*', $parser->next_value);
|
||||||
|
|
||||||
# Used to locate the signing certificate record
|
# Used to locate the signing certificate record
|
||||||
$header_serial_number = $serial_number;
|
$header_serial_number = $serial_number;
|
||||||
|
|
||||||
print 'Serial Number: ', join (':', $serial_number =~ m/(..)/g), "\n";
|
print 'Serial Number: ', join (':', $serial_number =~ m/(..)/g), "\n";
|
||||||
} elsif ($parser->tag == HEADER_CA_NAME) {
|
} elsif ($parser->tag == HEADER_CA_NAME) {
|
||||||
my $ca_name = unpack ('Z*', $parser->next_value);
|
my $ca_name = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'CA Name: ', $ca_name, "\n";
|
print 'CA Name: ', $ca_name, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE_INFO) {
|
} elsif ($parser->tag == HEADER_SIGNATURE_INFO) {
|
||||||
my $signature_info = $parser->length;
|
my $signature_info = $parser->length;
|
||||||
|
|
||||||
print 'Signature Info: ', $signature_info, "\n";
|
print 'Signature Info: ', $signature_info, "\n";
|
||||||
} elsif ($parser->tag == HEADER_DIGEST_ALGORITHM) {
|
} elsif ($parser->tag == HEADER_DIGEST_ALGORITHM) {
|
||||||
die 'Invalid digest_algorithm length: ' . $parser->length if ($parser->length != 1);
|
die 'Invalid digest_algorithm length: ' . $parser->length if ($parser->length != 1);
|
||||||
|
|
||||||
my $digest_algorithm = unpack ('C', $parser->next_value);
|
my $digest_algorithm = unpack ('C', $parser->next_value);
|
||||||
|
|
||||||
$header_digest_algorithm = $digest_algorithm;
|
$header_digest_algorithm = $digest_algorithm;
|
||||||
|
|
||||||
print 'Digest Algorithm: ';
|
print 'Digest Algorithm: ';
|
||||||
|
|
||||||
if ($digest_algorithm == DIGEST_SHA1) {
|
if ($digest_algorithm == DIGEST_SHA1) {
|
||||||
print 'SHA1';
|
print 'SHA1';
|
||||||
} elsif ($digest_algorithm == DIGEST_SHA256) {
|
} elsif ($digest_algorithm == DIGEST_SHA256) {
|
||||||
print 'SHA256';
|
print 'SHA256';
|
||||||
}
|
}
|
||||||
|
|
||||||
print "\n";
|
print "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE_ALGORITHM_INFO) {
|
} elsif ($parser->tag == HEADER_SIGNATURE_ALGORITHM_INFO) {
|
||||||
my $signature_algorithm_info = $parser->length;
|
my $signature_algorithm_info = $parser->length;
|
||||||
|
|
||||||
print 'Signature Algorithm Info: ', $signature_algorithm_info, "\n";
|
print 'Signature Algorithm Info: ', $signature_algorithm_info, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE_ALGORITHM) {
|
} elsif ($parser->tag == HEADER_SIGNATURE_ALGORITHM) {
|
||||||
die 'Invalid signature_algorithm length: ' . $parser->length if ($parser->length != 1);
|
die 'Invalid signature_algorithm length: ' . $parser->length if ($parser->length != 1);
|
||||||
|
|
||||||
my $signature_algorithm = unpack ('C', $parser->next_value);
|
my $signature_algorithm = unpack ('C', $parser->next_value);
|
||||||
|
|
||||||
print 'Signature Algorithm: ', $signature_algorithm, "\n";
|
print 'Signature Algorithm: ', $signature_algorithm, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE_MODULUS) {
|
} elsif ($parser->tag == HEADER_SIGNATURE_MODULUS) {
|
||||||
die 'Invalid signature_modulus length: ' . $parser->length if ($parser->length != 1);
|
die 'Invalid signature_modulus length: ' . $parser->length if ($parser->length != 1);
|
||||||
|
|
||||||
my $signature_modulus = unpack ('C', $parser->next_value);
|
my $signature_modulus = unpack ('C', $parser->next_value);
|
||||||
|
|
||||||
print 'Signature Modulus: ', $signature_modulus, "\n";
|
print 'Signature Modulus: ', $signature_modulus, "\n";
|
||||||
} elsif ($parser->tag == HEADER_SIGNATURE) {
|
} elsif ($parser->tag == HEADER_SIGNATURE) {
|
||||||
my $signature = $parser->next_value;
|
my $signature = $parser->next_value;
|
||||||
|
|
||||||
# The removal index for the signature
|
# The removal index for the signature
|
||||||
$header_signature_index = $parser->index - $parser->length - 3;
|
$header_signature_index = $parser->index - $parser->length - 3;
|
||||||
$header_signature_length = $parser->length + 3;
|
$header_signature_length = $parser->length + 3;
|
||||||
|
|
||||||
print 'Signature: ', length ($signature), ' bytes', "\n";
|
print 'Signature: ', length ($signature), ' bytes', "\n";
|
||||||
} elsif ($parser->tag == HEADER_FILENAME) {
|
} elsif ($parser->tag == HEADER_FILENAME) {
|
||||||
my $filename = unpack ('Z*', $parser->next_value);
|
my $filename = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'Filename: ', $filename, "\n";
|
print 'Filename: ', $filename, "\n";
|
||||||
} elsif ($parser->tag == HEADER_TIMESTAMP) {
|
} elsif ($parser->tag == HEADER_TIMESTAMP) {
|
||||||
die 'Invalid timestamp length: ' . $parser->length if ($parser->length != 4);
|
die 'Invalid timestamp length: ' . $parser->length if ($parser->length != 4);
|
||||||
|
|
||||||
my $timestamp = unpack ('L>', $parser->next_value);
|
my $timestamp = unpack ('L>', $parser->next_value);
|
||||||
|
|
||||||
print 'Timestamp: ', strftime ('%a, %d %b %Y %H:%M:%S %z', localtime $timestamp), "\n";
|
print 'Timestamp: ', strftime ('%a, %d %b %Y %H:%M:%S %z', localtime $timestamp), "\n";
|
||||||
} else {
|
} else {
|
||||||
die 'Unknown tag: ' . $parser->tag . ' at index: ' . ($parser->index - 3);
|
die 'Unknown tag: ' . $parser->tag . ' at index: ' . ($parser->index - 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print "\n";
|
print "\n";
|
||||||
@@ -145,90 +145,84 @@ sub parse_tlv {
|
|||||||
$record_number = 0;
|
$record_number = 0;
|
||||||
|
|
||||||
until ($parser->done) {
|
until ($parser->done) {
|
||||||
die 'Not a record_length tag: ' . $parser->tag if ($parser->next_tag != RECORD_LENGTH);
|
die 'Not a record_length tag: ' . $parser->tag if ($parser->next_tag != RECORD_LENGTH);
|
||||||
die 'Wrong record_length length: ' . $parser->length if ($parser->next_length != 2);
|
die 'Wrong record_length length: ' . $parser->length if ($parser->next_length != 2);
|
||||||
|
|
||||||
my $record_length = unpack ('S>', $parser->next_value);
|
my $record_length = unpack ('S>', $parser->next_value);
|
||||||
my $record_index = $parser->index - $parser->length - 3;
|
my $record_index = $parser->index - $parser->length - 3;
|
||||||
|
|
||||||
$record_number++;
|
$record_number++;
|
||||||
|
|
||||||
print 'Record Number: ', $record_number, "\n",
|
print 'Record Number: ', $record_number, "\n",
|
||||||
'Record Length: ', $record_length, ' bytes', "\n";
|
'Record Length: ', $record_length, ' bytes', "\n";
|
||||||
|
|
||||||
my ($record_function, $record_serial_number);
|
my ($record_function, $record_serial_number);
|
||||||
|
|
||||||
while ($parser->index - $record_index < $record_length) {
|
while ($parser->index - $record_index < $record_length) {
|
||||||
$parser->next_tag;
|
$parser->next_tag;
|
||||||
$parser->next_length;
|
$parser->next_length;
|
||||||
|
|
||||||
if ($parser->tag == RECORD_DNS_NAME) {
|
if ($parser->tag == RECORD_DNS_NAME) {
|
||||||
my $dns_name = unpack ('Z*', $parser->next_value);
|
my $dns_name = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'DNS Name: ', $dns_name, "\n";
|
print 'DNS Name: ', $dns_name, "\n";
|
||||||
} elsif ($parser->tag == RECORD_SUBJECT_NAME) {
|
} elsif ($parser->tag == RECORD_SUBJECT_NAME) {
|
||||||
my $subject_name = unpack ('Z*', $parser->next_value);
|
my $subject_name = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'Subject Name: ', $subject_name, "\n";
|
print 'Subject Name: ', $subject_name, "\n";
|
||||||
} elsif ($parser->tag == RECORD_FUNCTION) {
|
} elsif ($parser->tag == RECORD_FUNCTION) {
|
||||||
my $function = unpack ('S>', $parser->next_value);
|
my $function = unpack ('S>', $parser->next_value);
|
||||||
|
|
||||||
$record_function = $function;
|
$record_function = $function;
|
||||||
|
|
||||||
print 'Function: ';
|
print 'Function: ';
|
||||||
|
|
||||||
if ($function == FUNCTION_SAST) {
|
if ($function == FUNCTION_SAST) {
|
||||||
print 'SAST';
|
print 'SAST';
|
||||||
} elsif ($function == FUNCTION_CCM) {
|
} elsif ($function == FUNCTION_CCM) {
|
||||||
print 'CCM';
|
print 'CCM';
|
||||||
} elsif ($function == FUNCTION_CCM_TFTP) {
|
} elsif ($function == FUNCTION_CCM_TFTP) {
|
||||||
print 'CCM+TFTP';
|
print 'CCM+TFTP';
|
||||||
} elsif ($function == FUNCTION_TFTP) {
|
} elsif ($function == FUNCTION_TFTP) {
|
||||||
print 'TFTP';
|
print 'TFTP';
|
||||||
} elsif ($function == FUNCTION_CAPF) {
|
} elsif ($function == FUNCTION_HTTPS) {
|
||||||
print 'CAPF';
|
print 'HTTPS';
|
||||||
} elsif ($function == FUNCTION_SRST) {
|
}
|
||||||
print 'SRST';
|
|
||||||
} elsif ($function == FUNCTION_HTTPS) {
|
|
||||||
print 'HTTPS';
|
|
||||||
} elsif ($function == FUNCTION_TVS) {
|
|
||||||
print 'TVS';
|
|
||||||
}
|
|
||||||
|
|
||||||
print "\n";
|
print "\n";
|
||||||
} elsif ($parser->tag == RECORD_ISSUER_NAME) {
|
} elsif ($parser->tag == RECORD_ISSUER_NAME) {
|
||||||
my $issuer_name = unpack ('Z*', $parser->next_value);
|
my $issuer_name = unpack ('Z*', $parser->next_value);
|
||||||
|
|
||||||
print 'Issuer Name: ', $issuer_name, "\n";
|
print 'Issuer Name: ', $issuer_name, "\n";
|
||||||
} elsif ($parser->tag == RECORD_SERIAL_NUMBER) {
|
} elsif ($parser->tag == RECORD_SERIAL_NUMBER) {
|
||||||
my $serial_number = uc unpack ('H*', $parser->next_value);
|
my $serial_number = uc unpack ('H*', $parser->next_value);
|
||||||
|
|
||||||
$record_serial_number = $serial_number;
|
$record_serial_number = $serial_number;
|
||||||
|
|
||||||
print 'Serial Number: ', join (':', $serial_number =~ m/(..)/g), "\n";
|
print 'Serial Number: ', join (':', $serial_number =~ m/(..)/g), "\n";
|
||||||
} elsif ($parser->tag == RECORD_PUBLIC_KEY) {
|
} elsif ($parser->tag == RECORD_PUBLIC_KEY) {
|
||||||
my $public_key = $parser->next_value;
|
my $public_key = $parser->next_value;
|
||||||
|
|
||||||
print 'Public Key: ', length ($public_key), ' bytes', "\n";
|
print 'Public Key: ', length ($public_key), ' bytes', "\n";
|
||||||
} elsif ($parser->tag == RECORD_SIGNATURE) {
|
} elsif ($parser->tag == RECORD_SIGNATURE) {
|
||||||
my $signature = $parser->next_value;
|
my $signature = $parser->next_value;
|
||||||
|
|
||||||
print 'Signature: ', length ($signature), ' bytes', "\n";
|
print 'Signature: ', length ($signature), ' bytes', "\n";
|
||||||
} elsif ($parser->tag == RECORD_CERTIFICATE) {
|
} elsif ($parser->tag == RECORD_CERTIFICATE) {
|
||||||
my $certificate = $parser->next_value;
|
my $certificate = $parser->next_value;
|
||||||
|
|
||||||
# Records that have the same serial number as the header and SAST function are used for signing
|
# Records that have the same serial number as the header and SAST function are used for signing
|
||||||
if ($record_serial_number eq $header_serial_number && defined ($record_function) && $record_function == FUNCTION_SAST) {
|
if ($record_serial_number eq $header_serial_number && defined ($record_function) && $record_function == FUNCTION_SAST) {
|
||||||
$record_certificate = $certificate;
|
$record_certificate = $certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
print 'Certificate: ', length ($certificate), ' bytes', "\n";
|
print 'Certificate: ', length ($certificate), ' bytes', "\n";
|
||||||
} else {
|
} else {
|
||||||
die 'Invalid record tag: ' . $parser->tag . ' at index: ' . ($parser->index - 3);
|
die 'Invalid record tag: ' . $parser->tag . ' at index: ' . ($parser->index - 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print "\n";
|
print "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
die 'No record certificate' unless (length $record_certificate);
|
die 'No record certificate' unless (length $record_certificate);
|
||||||
@@ -240,11 +234,11 @@ sub parse_tlv {
|
|||||||
die 'Unable to parse RSA public key' unless ($rsa);
|
die 'Unable to parse RSA public key' unless ($rsa);
|
||||||
|
|
||||||
if ($header_digest_algorithm == DIGEST_SHA1) {
|
if ($header_digest_algorithm == DIGEST_SHA1) {
|
||||||
$rsa->use_sha1_hash;
|
$rsa->use_sha1_hash;
|
||||||
} elsif ($header_digest_algorithm == DIGEST_SHA256) {
|
} elsif ($header_digest_algorithm == DIGEST_SHA256) {
|
||||||
$rsa->use_sha256_hash;
|
$rsa->use_sha256_hash;
|
||||||
} else {
|
} else {
|
||||||
die 'Unknown header_digest_algorithm: ' . $header_digest_algorithm;
|
die 'Unknown header_digest_algorithm: ' . $header_digest_algorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = $parser->content;
|
$content = $parser->content;
|
||||||
@@ -254,9 +248,9 @@ sub parse_tlv {
|
|||||||
substr ($content, $header_signature_index, $header_signature_length, '');
|
substr ($content, $header_signature_index, $header_signature_length, '');
|
||||||
|
|
||||||
if ($rsa->verify ($content, $signature)) {
|
if ($rsa->verify ($content, $signature)) {
|
||||||
print 'Valid signature', "\n";
|
print 'Valid signature', "\n";
|
||||||
} else {
|
} else {
|
||||||
print 'Invalid signature', "\n";
|
print 'Invalid signature', "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +269,7 @@ sub build_tlv {
|
|||||||
my ($file, $content);
|
my ($file, $content);
|
||||||
|
|
||||||
unless ($file = IO::File->new ($certificate_file, '<:raw')) {
|
unless ($file = IO::File->new ($certificate_file, '<:raw')) {
|
||||||
die 'Unable to read ' . $certificate_file . ': ' . $OS_ERROR;
|
die 'Unable to read ' . $certificate_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
||||||
@@ -288,207 +282,201 @@ sub build_tlv {
|
|||||||
die 'Unable to load header private key' unless ($rsa);
|
die 'Unable to load header private key' unless ($rsa);
|
||||||
|
|
||||||
if ($digest_algorithm eq 'SHA1') {
|
if ($digest_algorithm eq 'SHA1') {
|
||||||
$rsa->use_sha1_hash;
|
$rsa->use_sha1_hash;
|
||||||
} elsif ($digest_algorithm eq 'SHA256') {
|
} elsif ($digest_algorithm eq 'SHA256') {
|
||||||
$rsa->use_sha256_hash;
|
$rsa->use_sha256_hash;
|
||||||
} else {
|
} else {
|
||||||
die 'Unknown digest_algorithm: ' . $digest_algorithm;
|
die 'Unknown digest_algorithm: ' . $digest_algorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $builder = TLV::Builder->new;
|
my $builder = TLV::Builder->new;
|
||||||
my $header_signature_index;
|
my $header_signature_index;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
# Header
|
# Header
|
||||||
$builder->next_tag (HEADER_VERSION);
|
$builder->next_tag (HEADER_VERSION);
|
||||||
$builder->next_length (2);
|
$builder->next_length (2);
|
||||||
$builder->next_value (pack ('CC', 1, 2));
|
$builder->next_value (pack ('CC', 1, 2));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_LENGTH);
|
$builder->next_tag (HEADER_LENGTH);
|
||||||
$builder->next_length (2);
|
$builder->next_length (2);
|
||||||
$builder->next_value (pack ('S>', 0));
|
$builder->next_value (pack ('S>', 0));
|
||||||
|
|
||||||
(my $signer_name = $x509->subject) =~ s/, /;/g;
|
(my $signer_name = $x509->subject) =~ s/, /;/g;
|
||||||
(my $ca_name = $x509->issuer) =~ s/, /;/g;
|
(my $ca_name = $x509->issuer) =~ s/, /;/g;
|
||||||
my $serial_number = pack ('H*', $x509->serial);
|
my $serial_number = pack ('H*', $x509->serial);
|
||||||
|
|
||||||
# Combined TLV length for signer_name, serial_number and ca_name
|
# Combined TLV length for signer_name, serial_number and ca_name
|
||||||
my $signer_id = 3 + length ($signer_name) + 1 + 3 + length ($serial_number) + 3 + length ($ca_name) + 1;
|
my $signer_id = 3 + length ($signer_name) + 1 + 3 + length ($serial_number) + 3 + length ($ca_name) + 1;
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNER_ID);
|
$builder->next_tag (HEADER_SIGNER_ID);
|
||||||
$builder->next_length ($signer_id);
|
$builder->next_length ($signer_id);
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNER_NAME);
|
$builder->next_tag (HEADER_SIGNER_NAME);
|
||||||
$builder->next_length (length ($signer_name) + 1);
|
$builder->next_length (length ($signer_name) + 1);
|
||||||
$builder->next_value (pack ('Z*', $signer_name));
|
$builder->next_value (pack ('Z*', $signer_name));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SERIAL_NUMBER);
|
$builder->next_tag (HEADER_SERIAL_NUMBER);
|
||||||
$builder->next_length (length $serial_number);
|
$builder->next_length (length $serial_number);
|
||||||
$builder->next_value ($serial_number);
|
$builder->next_value ($serial_number);
|
||||||
|
|
||||||
$builder->next_tag (HEADER_CA_NAME);
|
$builder->next_tag (HEADER_CA_NAME);
|
||||||
$builder->next_length (length ($ca_name) + 1);
|
$builder->next_length (length ($ca_name) + 1);
|
||||||
$builder->next_value (pack ('Z*', $ca_name));
|
$builder->next_value (pack ('Z*', $ca_name));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNATURE_INFO);
|
$builder->next_tag (HEADER_SIGNATURE_INFO);
|
||||||
$builder->next_length (15); # Unknown
|
$builder->next_length (15); # Unknown
|
||||||
|
|
||||||
$builder->next_tag (HEADER_DIGEST_ALGORITHM);
|
$builder->next_tag (HEADER_DIGEST_ALGORITHM);
|
||||||
$builder->next_length (1);
|
$builder->next_length (1);
|
||||||
$builder->next_value (pack ('C', do {
|
$builder->next_value (pack ('C', do {
|
||||||
if ($digest_algorithm eq 'SHA1') {
|
if ($digest_algorithm eq 'SHA1') {
|
||||||
DIGEST_SHA1;
|
DIGEST_SHA1;
|
||||||
} elsif ($digest_algorithm eq 'SHA256') {
|
} elsif ($digest_algorithm eq 'SHA256') {
|
||||||
DIGEST_SHA256;
|
DIGEST_SHA256;
|
||||||
} else {
|
} else {
|
||||||
die 'Unknown digest algorithm: ' . $digest_algorithm;
|
die 'Unknown digest algorithm: ' . $digest_algorithm;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNATURE_ALGORITHM_INFO);
|
$builder->next_tag (HEADER_SIGNATURE_ALGORITHM_INFO);
|
||||||
$builder->next_length (8); # Unknown
|
$builder->next_length (8); # Unknown
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNATURE_ALGORITHM);
|
$builder->next_tag (HEADER_SIGNATURE_ALGORITHM);
|
||||||
$builder->next_length (1);
|
$builder->next_length (1);
|
||||||
$builder->next_value (pack ('C', 0)); # Unknown
|
$builder->next_value (pack ('C', 0)); # Unknown
|
||||||
|
|
||||||
my $signature_modulus;
|
my $signature_modulus;
|
||||||
|
|
||||||
if ($rsa->size == 64) {
|
if ($rsa->size == 64) {
|
||||||
$signature_modulus = 0;
|
$signature_modulus = 0;
|
||||||
} elsif ($rsa->size == 128) {
|
} elsif ($rsa->size == 128) {
|
||||||
$signature_modulus = 1;
|
$signature_modulus = 1;
|
||||||
} elsif ($rsa->size == 256) {
|
} elsif ($rsa->size == 256) {
|
||||||
$signature_modulus = 2;
|
$signature_modulus = 2;
|
||||||
} elsif ($rsa->size == 512) {
|
} elsif ($rsa->size == 512) {
|
||||||
$signature_modulus = 3;
|
$signature_modulus = 3;
|
||||||
} else {
|
} else {
|
||||||
die 'Unsupported RSA key size: ' . $rsa->size;
|
die 'Unsupported RSA key size: ' . $rsa->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
$builder->next_tag (HEADER_SIGNATURE_MODULUS);
|
$builder->next_tag (HEADER_SIGNATURE_MODULUS);
|
||||||
$builder->next_length (1);
|
$builder->next_length (1);
|
||||||
$builder->next_value (pack ('C', $signature_modulus));
|
$builder->next_value (pack ('C', $signature_modulus));
|
||||||
|
|
||||||
# The insertion index of the signature
|
# The insertion index of the signature
|
||||||
$header_signature_index = $builder->index;
|
$header_signature_index = $builder->index;
|
||||||
|
|
||||||
$builder->next_tag (HEADER_FILENAME);
|
$builder->next_tag (HEADER_FILENAME);
|
||||||
$builder->next_length (length ($filename) + 1);
|
$builder->next_length (length ($filename) + 1);
|
||||||
$builder->next_value (pack ('Z*', $filename));
|
$builder->next_value (pack ('Z*', $filename));
|
||||||
|
|
||||||
$builder->next_tag (HEADER_TIMESTAMP);
|
$builder->next_tag (HEADER_TIMESTAMP);
|
||||||
$builder->next_length (4);
|
$builder->next_length (4);
|
||||||
$builder->next_value (pack ('L>', time));
|
$builder->next_value (pack ('L>', time));
|
||||||
|
|
||||||
# Header must be padded to 32-bit boundary
|
# Header must be padded to 32-bit boundary
|
||||||
while (($builder->index + 3 + $rsa->size) % 4) {
|
while (($builder->index + 3 + $rsa->size) % 4) {
|
||||||
$builder->next_tag (HEADER_PADDING);
|
$builder->next_tag (HEADER_PADDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Signed content includes the length of the signature block
|
# Signed content includes the length of the signature block
|
||||||
$builder->length (8, $builder->index + 3 + $rsa->size);
|
$builder->length (8, $builder->index + 3 + $rsa->size);
|
||||||
};
|
};
|
||||||
|
|
||||||
# Records
|
# Records
|
||||||
foreach my $record (@{$records}) {
|
foreach my $record (@{$records}) {
|
||||||
my ($certificate_file, $function) = ($record->{certificate_file}, $record->{function});
|
my ($certificate_file, $function) = ($record->{certificate_file}, $record->{function});
|
||||||
|
|
||||||
my ($file, $content);
|
my ($file, $content);
|
||||||
|
|
||||||
unless ($file = IO::File->new ($certificate_file, '<:raw')) {
|
unless ($file = IO::File->new ($certificate_file, '<:raw')) {
|
||||||
die 'Unable to read ' . $certificate_file . ': ' . $OS_ERROR;
|
die 'Unable to read ' . $certificate_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
$content = do {local $INPUT_RECORD_SEPARATOR; $file->getline};
|
||||||
$file->close;
|
$file->close;
|
||||||
|
|
||||||
my $x509 = Crypt::OpenSSL::X509->new_from_string ($content, FORMAT_PEM);
|
my $x509 = Crypt::OpenSSL::X509->new_from_string ($content, FORMAT_PEM);
|
||||||
die 'Unable to load record certificate' unless ($x509);
|
die 'Unable to load record certificate' unless ($x509);
|
||||||
|
|
||||||
my $record_index = $builder->index;
|
my $record_index = $builder->index;
|
||||||
|
|
||||||
$builder->next_tag (RECORD_LENGTH);
|
$builder->next_tag (RECORD_LENGTH);
|
||||||
$builder->next_length (2);
|
$builder->next_length (2);
|
||||||
$builder->next_value (pack ('S>', 0));
|
$builder->next_value (pack ('S>', 0));
|
||||||
|
|
||||||
unless ($function eq 'SAST') {
|
unless ($function eq 'SAST') {
|
||||||
(my $dns_name) = ($x509->subject =~ m/\bCN=([^,]+)/);
|
(my $dns_name) = ($x509->subject =~ m/\bCN=([^,]+)/);
|
||||||
|
|
||||||
# DNS name is included even if empty
|
# DNS name is included even if empty
|
||||||
$builder->next_tag (RECORD_DNS_NAME);
|
$builder->next_tag (RECORD_DNS_NAME);
|
||||||
$builder->next_length (length ($dns_name) + 1);
|
$builder->next_length (length ($dns_name) + 1);
|
||||||
$builder->next_value (pack ('Z*', $dns_name));
|
$builder->next_value (pack ('Z*', $dns_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
(my $subject_name = $x509->subject) =~ s/, /;/g;
|
(my $subject_name = $x509->subject) =~ s/, /;/g;
|
||||||
|
|
||||||
$builder->next_tag (RECORD_SUBJECT_NAME);
|
$builder->next_tag (RECORD_SUBJECT_NAME);
|
||||||
$builder->next_length (length ($subject_name) + 1);
|
$builder->next_length (length ($subject_name) + 1);
|
||||||
$builder->next_value (pack ('Z*', $subject_name));
|
$builder->next_value (pack ('Z*', $subject_name));
|
||||||
|
|
||||||
$builder->next_tag (RECORD_FUNCTION);
|
$builder->next_tag (RECORD_FUNCTION);
|
||||||
$builder->next_length (2);
|
$builder->next_length (2);
|
||||||
$builder->next_value (pack ('S>', do {
|
$builder->next_value (pack ('S>', do {
|
||||||
if ($function eq 'SAST') {
|
if ($function eq 'SAST') {
|
||||||
FUNCTION_SAST;
|
FUNCTION_SAST;
|
||||||
} elsif ($function eq 'CCM') {
|
} elsif ($function eq 'CCM') {
|
||||||
FUNCTION_CCM;
|
FUNCTION_CCM;
|
||||||
} elsif ($function eq 'CCM+TFTP') {
|
} elsif ($function eq 'CCM+TFTP') {
|
||||||
FUNCTION_CCM_TFTP;
|
FUNCTION_CCM_TFTP;
|
||||||
} elsif ($function eq 'TFTP') {
|
} elsif ($function eq 'TFTP') {
|
||||||
FUNCTION_TFTP;
|
FUNCTION_TFTP;
|
||||||
} elsif ($function eq 'CAPF') {
|
} elsif ($function eq 'HTTPS') {
|
||||||
FUNCTION_CAPF;
|
FUNCTION_HTTPS;
|
||||||
} elsif ($function eq 'SRST') {
|
} else {
|
||||||
FUNCTION_SRST;
|
die 'Unknown record function: ' . $function;
|
||||||
} elsif ($function eq 'HTTPS') {
|
};
|
||||||
FUNCTION_HTTPS;
|
}));
|
||||||
} elsif ($function eq 'TVS') {
|
|
||||||
FUNCTION_TVS;
|
|
||||||
} else {
|
|
||||||
die 'Unknown record function: ' . $function;
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
(my $issuer_name = $x509->issuer) =~ s/, /;/g;
|
(my $issuer_name = $x509->issuer) =~ s/, /;/g;
|
||||||
|
|
||||||
$builder->next_tag (RECORD_ISSUER_NAME);
|
$builder->next_tag (RECORD_ISSUER_NAME);
|
||||||
$builder->next_length (length ($issuer_name) + 1);
|
$builder->next_length (length ($issuer_name) + 1);
|
||||||
$builder->next_value (pack ('Z*', $issuer_name));
|
$builder->next_value (pack ('Z*', $issuer_name));
|
||||||
|
|
||||||
my $serial_number = pack ('H*', $x509->serial);
|
my $serial_number = pack ('H*', $x509->serial);
|
||||||
|
|
||||||
$builder->next_tag (RECORD_SERIAL_NUMBER);
|
$builder->next_tag (RECORD_SERIAL_NUMBER);
|
||||||
$builder->next_length (length $serial_number);
|
$builder->next_length (length $serial_number);
|
||||||
$builder->next_value ($serial_number);
|
$builder->next_value ($serial_number);
|
||||||
|
|
||||||
my $asn1 = Convert::ASN1->new;
|
my $asn1 = Convert::ASN1->new;
|
||||||
|
|
||||||
$asn1->prepare ('SEQUENCE { modulus INTEGER, exponent INTEGER }');
|
$asn1->prepare ('SEQUENCE { modulus INTEGER, exponent INTEGER }');
|
||||||
|
|
||||||
my $public_key = $asn1->encode ({modulus => Math::BigInt->from_hex ($x509->modulus),
|
my $public_key = $asn1->encode ({modulus => Math::BigInt->from_hex ($x509->modulus),
|
||||||
exponent => hex $x509->exponent});
|
exponent => hex $x509->exponent});
|
||||||
|
|
||||||
$builder->next_tag (RECORD_PUBLIC_KEY);
|
$builder->next_tag (RECORD_PUBLIC_KEY);
|
||||||
$builder->next_length (length $public_key);
|
$builder->next_length (length $public_key);
|
||||||
$builder->next_value ($public_key);
|
$builder->next_value ($public_key);
|
||||||
|
|
||||||
my $signature = pack ('H*', $x509->sig_print);
|
my $signature = pack ('H*', $x509->sig_print);
|
||||||
|
|
||||||
$builder->next_tag (RECORD_SIGNATURE);
|
$builder->next_tag (RECORD_SIGNATURE);
|
||||||
$builder->next_length (length $signature);
|
$builder->next_length (length $signature);
|
||||||
$builder->next_value ($signature);
|
$builder->next_value ($signature);
|
||||||
|
|
||||||
my $certificate = $x509->as_string (FORMAT_ASN1);
|
my $certificate = $x509->as_string (FORMAT_ASN1);
|
||||||
|
|
||||||
$builder->next_tag (RECORD_CERTIFICATE);
|
$builder->next_tag (RECORD_CERTIFICATE);
|
||||||
$builder->next_length (length $certificate);
|
$builder->next_length (length $certificate);
|
||||||
$builder->next_value ($certificate);
|
$builder->next_value ($certificate);
|
||||||
|
|
||||||
my $record_length = $builder->index - $record_index;
|
my $record_length = $builder->index - $record_index;
|
||||||
|
|
||||||
$builder->length ($record_index + 3, $record_length);
|
$builder->length ($record_index + 3, $record_length);
|
||||||
};
|
};
|
||||||
|
|
||||||
$content = $builder->content;
|
$content = $builder->content;
|
||||||
@@ -498,7 +486,7 @@ sub build_tlv {
|
|||||||
substr ($content, $header_signature_index, 0, pack ('CS>a*', HEADER_SIGNATURE, $rsa->size, $signature));
|
substr ($content, $header_signature_index, 0, pack ('CS>a*', HEADER_SIGNATURE, $rsa->size, $signature));
|
||||||
|
|
||||||
unless ($file = IO::File->new ($tlv_file, '>:raw')) {
|
unless ($file = IO::File->new ($tlv_file, '>:raw')) {
|
||||||
die 'Unable to write ' . $tlv_file . ': ' . $OS_ERROR;
|
die 'Unable to write ' . $tlv_file . ': ' . $OS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$file->print ($content);
|
$file->print ($content);
|
||||||
@@ -517,46 +505,46 @@ eval {
|
|||||||
$getopt->configure (qw/no_ignore_case/);
|
$getopt->configure (qw/no_ignore_case/);
|
||||||
|
|
||||||
unless ($getopt->getoptions ('p|parse' => sub {shift; $mode = 'parse'},
|
unless ($getopt->getoptions ('p|parse' => sub {shift; $mode = 'parse'},
|
||||||
'b|build' => sub {shift; $mode = 'build'},
|
'b|build' => sub {shift; $mode = 'build'},
|
||||||
'c|certificate=s' => sub {shift; $certificate_file = shift},
|
'c|certificate=s' => sub {shift; $certificate_file = shift},
|
||||||
'd|digest=s' => sub {shift; $digest_algorithm = uc shift},
|
'd|digest=s' => sub {shift; $digest_algorithm = uc shift},
|
||||||
'r|record=s' => sub {shift; push (@{$records}, $record = {certificate_file => shift})},
|
'r|record=s' => sub {shift; push (@{$records}, $record = {certificate_file => shift})},
|
||||||
'f|function=s' => sub {shift; $record->{function} = uc shift if $record},
|
'f|function=s' => sub {shift; $record->{function} = uc shift if $record},
|
||||||
'F|filename=s' => sub {shift; $filename = shift},
|
'F|filename=s' => sub {shift; $filename = shift},
|
||||||
'h|help' => sub {shift; $show_help = shift})) {
|
'h|help' => sub {shift; $show_help = shift})) {
|
||||||
die 'Error parsing options';
|
die 'Error parsing options';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($show_help) {
|
if ($show_help) {
|
||||||
print 'Usage: ', basename ($PROGRAM_NAME), ' <FILE> [OPTIONS]', "\n",
|
print 'Usage: ', basename ($PROGRAM_NAME), ' <FILE> [OPTIONS]', "\n",
|
||||||
'Parse or build a .tlv file', "\n",
|
'Parse or build a .tlv file', "\n",
|
||||||
"\n",
|
"\n",
|
||||||
' -p --parse parse a .tlv file', "\n",
|
' -p --parse parse a .tlv file', "\n",
|
||||||
' -b --build build a .tlv file', "\n",
|
' -b --build build a .tlv file', "\n",
|
||||||
' -c --certificate <file> certificate to use for verifying or signing', "\n",
|
' -c --certificate <file> certificate to use for verifying or signing', "\n",
|
||||||
' -d --digest <name> signature digest (sha1, sha256)', "\n",
|
' -d --digest <name> signature digest (sha1, sha256)', "\n",
|
||||||
' -F --filename <name> header filename in built .tlv file (optional)', "\n",
|
' -F --filename <name> header filename in built .tlv file (optional)', "\n",
|
||||||
' -r --record <file> additional record certificate', "\n",
|
' -r --record <file> additional record certificate', "\n",
|
||||||
' -f --function <name> record function (sast, ccm, ccm+tftp tftp, https)', "\n",
|
' -f --function <name> record function (sast, ccm, ccm+tftp tftp, https)', "\n",
|
||||||
' -h --help print this help and exit', "\n",
|
' -h --help print this help and exit', "\n",
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
die 'No .tlv file specified' unless (length ($tlv_file = shift));
|
die 'No .tlv file specified' unless (length ($tlv_file = shift));
|
||||||
|
|
||||||
if ($mode eq 'parse') {
|
if ($mode eq 'parse') {
|
||||||
parse_tlv ($tlv_file);
|
parse_tlv ($tlv_file);
|
||||||
} elsif ($mode eq 'build') {
|
} elsif ($mode eq 'build') {
|
||||||
die 'No signing certificate file specified' unless (length $certificate_file);
|
die 'No signing certificate file specified' unless (length $certificate_file);
|
||||||
|
|
||||||
$digest_algorithm = 'SHA1' unless (length $digest_algorithm);
|
$digest_algorithm = 'SHA1' unless (length $digest_algorithm);
|
||||||
$filename = basename ($tlv_file) unless (length $filename);
|
$filename = basename ($tlv_file) unless (length $filename);
|
||||||
|
|
||||||
build_tlv ($tlv_file, $certificate_file, $digest_algorithm, $filename, $records);
|
build_tlv ($tlv_file, $certificate_file, $digest_algorithm, $filename, $records);
|
||||||
} else {
|
} else {
|
||||||
die 'No mode specified';
|
die 'No mode specified, choose either --build, --parse or --help for available options';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user