I have an ssl server (test) in c - and a client written in php. the server works fine when a client written in c connects, but when the php client (virtually identical to the c client) sends, the message appears on the server only after buffer overflow or disconnect.
why a c program and not a php program would work is a mystery to me.
I've tried buffer control, unblocking, adding nulls to the send string.
php 5.4 centos linux 2.6
i can add code if appropriate - it's quite vanilla. but i thought there might be a difference between the way php handles stream traffic and c. my confidence in my code.
thanks for any thoughts.
#!/usr/local/bin/php
<?php
date_default_timezone_set('America/New_York');
$host = 'localhost';
$port = 9255;
$timeout = 5.0;
function gen_cert($pem_file,$pem_passphrase)
{
// Certificate data:
$dn = array(
"countryName" => "US",
"stateOrProvinceName" => "Texas",
"localityName" => "Houston",
"organizationName" => "<org name>",
"organizationalUnitName" => "Tech",
"commonName" => "kensie2",
"emailAddress" => "<email>"
);
// Generate certificate
$privkey = openssl_pkey_new();
$cert = openssl_csr_new($dn, $privkey);
$cert = openssl_csr_sign($cert, null, $privkey, 365);
// Generate PEM file
$pem = array();
openssl_x509_export($cert, $pem[0]);
openssl_pkey_export($privkey, $pem[1], $pem_passphrase);
openssl_pkey_export($privkey, $pem[1], $pem_passphrase);
$pem = implode($pem);
// Save PEM file
// $pemfile = $filename;
file_put_contents($pem_file, $pem);
chmod($pem_file,0400);
}
$pem_passphrase = 'foozot';
$pem_file = 'test3_client.pem';
if(!file_exists($pem_file))
gen_cert($pem_file,$pem_passphrase);
$context = stream_context_create();
// local_cert must be in PEM format
stream_context_set_option($context, 'tls', 'local_cert', $pem_file);
// Pass Phrase (password) of private key
stream_context_set_option($context, 'tls', 'passphrase', $pem_passphrase);
stream_context_set_option($context, 'tls', 'allow_self_signed', true);
stream_context_set_option($context, 'tls', 'verify_peer', true);
$fp = stream_socket_client('tls://'.$host.':'.$port, $errno, $errstr, $timeout,
STREAM_CLIENT_CONNECT, $context);
if($fp)
{
$buf = fread($fp,8192);
fwrite(STDOUT,"from server: $buf");
// tried this - no difference
// stream_set_write_buffer($fp,0);
// tried this - no difference
// stream_set_blocking($fp,0);
$ary = stream_get_meta_data($fp);
fwrite(STDERR,"meta=" . print_r($ary,true) . "\n");
while(1)
{
$buf = fgets(STDIN);
fwrite(STDOUT,"buf=$buf\n");
if(strstr($buf,"\n") === null)
$buf .= "\n\0";
$er = fwrite($fp, $buf,strlen($buf) + 1);
fwrite(STDERR,posix_strerror(posix_get_last_error()) . "\n");
}
}
else
{
echo "ERROR: $errno - $errstr<br />\n";
}
?>
I'musing code from Professional Linux Network Programming - Chapter 8 - server.c
By Nathan Yocom, plnp#yocom.org modified to prefork. it uses BIO for io.
as a model for the c code. i don't think i can post it without some copyright violation.
it does work. far more tested than my code.
Related
I am working on below things:
Generate CSR(Certificate Signing Request)
Upload SSL Certificates
To generate SSL certificate I am using something like:
$privkey = openssl_pkey_new();
$csr = openssl_csr_new($dn, $privkey);
$sscert = openssl_csr_sign($csr, null, $privkey, $days);
openssl_csr_export($csr, $csrout);
openssl_pkey_export($privkey, $pkeyout, $_POST['password']);
openssl_pkey_export_to_file($privkey, "<path/to/store/server.key>");
openssl_csr_export_to_file($csr, "/tmp/".<domain-name>.".csr");
Now using that CSR request, I am able to generate(domain-name.cer),(DigitalCert.cer).
Now once I upload this(.cer) certificates, I need to verify those certificates.
Reason: Someone generated these certificates on say "a.com" and tries to upload on "b.com". this should not happen, so I want to validate the uploaded SSL certificates.
In PHP, we have
$ok = openssl_verify($data, $signature, $pubkeyid);
but i am not able to get what things would be treated as $data, $signature and $pubkeyid based on the above certificate generation process.
Check this out:
Verify SMTP in PHP
<?php
$server = "smtp.gmail.com"; // Who I connect to
$myself = "my_server.example.com"; // Who I am
$cabundle = '/etc/ssl/cacert.pem'; // Where my root certificates are
// Verify server. There's not much we can do, if we suppose that an attacker
// has taken control of the DNS. The most we can hope for is that there will
// be discrepancies between the expected responses to the following code and
// the answers from the subverted DNS server.
// To detect these discrepancies though, implies we knew the proper response
// and saved it in the code. At that point we might as well save the IP, and
// decouple from the DNS altogether.
$match1 = false;
$addrs = gethostbynamel($server);
foreach($addrs as $addr)
{
$name = gethostbyaddr($addr);
if ($name == $server)
{
$match1 = true;
break;
}
}
// Here we must decide what to do if $match1 is false.
// Which may happen often and for legitimate reasons.
print "Test 1: " . ($match1 ? "PASSED" : "FAILED") . "\n";
$match2 = false;
$domain = explode('.', $server);
array_shift($domain);
$domain = implode('.', $domain);
getmxrr($domain, $mxhosts);
foreach($mxhosts as $mxhost)
{
$tests = gethostbynamel($mxhost);
if (0 != count(array_intersect($addrs, $tests)))
{
// One of the instances of $server is a MX for its domain
$match2 = true;
break;
}
}
// Again here we must decide what to do if $match2 is false.
// Most small ISP pass test 2; very large ISPs and Google fail.
print "Test 2: " . ($match2 ? "PASSED" : "FAILED") . "\n";
// On the other hand, if you have a PASS on a server you use,
// it's unlikely to become a FAIL anytime soon.
// End of maybe-they-help-maybe-they-don't checks.
// Establish the connection
$smtp = fsockopen( "tcp://$server", 25, $errno, $errstr );
fread( $smtp, 512 );
// Here you can check the usual banner from $server (or in general,
// check whether it contains $server's domain name, or whether the
// domain it advertises has $server among its MX's.
// But yet again, Google fails both these tests.
fwrite($smtp,"HELO $myself\r\n");
fread($smtp, 512);
// Switch to TLS
fwrite($smtp,"STARTTLS\r\n");
fread($smtp, 512);
stream_set_blocking($smtp, true);
stream_context_set_option($smtp, 'ssl', 'verify_peer', true);
stream_context_set_option($smtp, 'ssl', 'allow_self_signed', false);
stream_context_set_option($smtp, 'ssl', 'capture_peer_cert', true);
stream_context_set_option($smtp, 'ssl', 'cafile', $cabundle);
$secure = stream_socket_enable_crypto($smtp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
stream_set_blocking($smtp, false);
$opts = stream_context_get_options($smtp);
if (!isset($opts["ssl"]["peer_certificate"]))
$secure = false;
else
{
$cert = openssl_x509_parse($opts["ssl"]["peer_certificate"]);
$names = '';
if ('' != $cert)
{
if (isset($cert['extensions']))
$names = $cert['extensions']['subjectAltName'];
elseif (isset($cert['subject']))
{
if (isset($cert['subject']['CN']))
$names = 'DNS:' . $cert['subject']['CN'];
else
$secure = false; // No exts, subject without CN
}
else
$secure = false; // No exts, no subject
}
$checks = explode(',', $names);
// At least one $check must match $server
$tmp = explode('.', $server);
$fles = array_reverse($tmp);
$okay = false;
foreach($checks as $check)
{
$tmp = explode(':', $check);
if ('DNS' != $tmp[0]) continue; // candidates must start with DNS:
if (!isset($tmp[1])) continue; // and have something afterwards
$tmp = explode('.', $tmp[1]);
if (count($tmp) < 3) continue; // "*.com" is not a valid match
$cand = array_reverse($tmp);
$okay = true;
foreach($cand as $i => $item)
{
if (!isset($fles[$i]))
{
// We connected to www.example.com and certificate is for *.www.example.com -- bad.
$okay = false;
break;
}
if ($fles[$i] == $item)
continue;
if ($item == '*')
break;
}
if ($okay)
break;
}
if (!$okay)
$secure = false; // No hosts matched our server.
}
if (!$secure)
die("failed to connect securely\n");
print "Success!\n";
// Continue with connection...
?>
This works for me
$crt_md5=exec('openssl x509 -noout -modulus -in /path/to/domain.crt/ | openssl md5 | sed "s/^.* //"');
$key_md5=exec('openssl rsa -noout -modulus -in /path/to/server.key | openssl md5 | sed "s/^.* //"');
if($crt_md5 != $key_md5){
echo 'BAD';
}
else{
echo "GOOD";
}
sed "s/^.* //" - will remove (stdin)= thing from the output, so that
you get exact md5 string
this is how i do it...
system('openssl x509 -noout -modulus -in '.$crt.' | openssl md5', $crt_md5);
system('openssl rsa -noout -modulus -in '.$key.' | openssl md5', $key_md5);
if($crt_md5 != $key_md5){
echo 'BAD';
}
Try openssl_x509_check_private_key( $crt, $key ) it returns boolean
ref http://php.net/manual/en/function.openssl-x509-check-private-key.php
WARNING: openssl_x509_check_private_key will not work for some case.
Example:
SSL certificate like this:
-----BEGIN CERTIFICATE-----
xxxx
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
xxxx
xxxx
This certificate does not end with -----END CERTIFICATE----- , but it can still pass the check of this function. It will return true to tell you that it is correct, but it is not actually. If you upload this certificate to your application, such as Nginx , Nginx will tell you an error.
This doesn't seem to be an error that only appears in PHP. If you check with the openssl function on the command line, it will tell you the same result.
So I think the best way is that you need to check whether the paragraphs of the certificate are complete.
After confirming that the format is correct, use this function to verify the certificate and private key.
In the command line, I can verify that certificate is issued by trusted CA by typing
openssl verify mycert.pem
How do I do same with PHP's OpenSSL library? PHP has an openssl_verify function which takes many extra parameters:
data , string $signature , mixed $pub_key_id
How do I repeat that simple command line operation with corresponding PHP function?
This is pretty easy with phpseclib, a pure PHP X509 implementation. eg.
<?php
include('File/X509.php');
$x509 = new File_X509();
$x509->loadCA('...');
$x509->loadX509('...');
echo $x509->validateSignature() ? 'valid' : 'invalid';
?>
See http://phpseclib.sourceforge.net/x509/compare.html#verify for more info
I'm not sure what is your cert but I found this function openssl_x509_checkpurpose.
http://php.net/manual/en/function.openssl-x509-checkpurpose.php
http://www.php.net/manual/en/openssl.cert.verification.php
openssl_x509_checkpurpose($cert, $purpose, $cainfo, $untrustedfile);
$cainfo is array with path to CA files.
In PHP the openssl_verify function is not used to verify that a certificate is issued by a trusted CA but used to verify that a signature is the right one for some data...
EDIT : How to verify CA with PHP :
You can't only verify that subject and issuer name are matching, so by only using OpenSSL in Php it doesnt seem like totally possible
check this out:
Verify SMTP in PHP
<?php
$server = "smtp.gmail.com"; // Who I connect to
$myself = "my_server.example.com"; // Who I am
$cabundle = '/etc/ssl/cacert.pem'; // Where my root certificates are
// Verify server. There's not much we can do, if we suppose that an attacker
// has taken control of the DNS. The most we can hope for is that there will
// be discrepancies between the expected responses to the following code and
// the answers from the subverted DNS server.
// To detect these discrepancies though, implies we knew the proper response
// and saved it in the code. At that point we might as well save the IP, and
// decouple from the DNS altogether.
$match1 = false;
$addrs = gethostbynamel($server);
foreach($addrs as $addr)
{
$name = gethostbyaddr($addr);
if ($name == $server)
{
$match1 = true;
break;
}
}
// Here we must decide what to do if $match1 is false.
// Which may happen often and for legitimate reasons.
print "Test 1: " . ($match1 ? "PASSED" : "FAILED") . "\n";
$match2 = false;
$domain = explode('.', $server);
array_shift($domain);
$domain = implode('.', $domain);
getmxrr($domain, $mxhosts);
foreach($mxhosts as $mxhost)
{
$tests = gethostbynamel($mxhost);
if (0 != count(array_intersect($addrs, $tests)))
{
// One of the instances of $server is a MX for its domain
$match2 = true;
break;
}
}
// Again here we must decide what to do if $match2 is false.
// Most small ISP pass test 2; very large ISPs and Google fail.
print "Test 2: " . ($match2 ? "PASSED" : "FAILED") . "\n";
// On the other hand, if you have a PASS on a server you use,
// it's unlikely to become a FAIL anytime soon.
// End of maybe-they-help-maybe-they-don't checks.
// Establish the connection
$smtp = fsockopen( "tcp://$server", 25, $errno, $errstr );
fread( $smtp, 512 );
// Here you can check the usual banner from $server (or in general,
// check whether it contains $server's domain name, or whether the
// domain it advertises has $server among its MX's.
// But yet again, Google fails both these tests.
fwrite($smtp,"HELO $myself\r\n");
fread($smtp, 512);
// Switch to TLS
fwrite($smtp,"STARTTLS\r\n");
fread($smtp, 512);
stream_set_blocking($smtp, true);
stream_context_set_option($smtp, 'ssl', 'verify_peer', true);
stream_context_set_option($smtp, 'ssl', 'allow_self_signed', false);
stream_context_set_option($smtp, 'ssl', 'capture_peer_cert', true);
stream_context_set_option($smtp, 'ssl', 'cafile', $cabundle);
$secure = stream_socket_enable_crypto($smtp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
stream_set_blocking($smtp, false);
$opts = stream_context_get_options($smtp);
if (!isset($opts["ssl"]["peer_certificate"]))
$secure = false;
else
{
$cert = openssl_x509_parse($opts["ssl"]["peer_certificate"]);
$names = '';
if ('' != $cert)
{
if (isset($cert['extensions']))
$names = $cert['extensions']['subjectAltName'];
elseif (isset($cert['subject']))
{
if (isset($cert['subject']['CN']))
$names = 'DNS:' . $cert['subject']['CN'];
else
$secure = false; // No exts, subject without CN
}
else
$secure = false; // No exts, no subject
}
$checks = explode(',', $names);
// At least one $check must match $server
$tmp = explode('.', $server);
$fles = array_reverse($tmp);
$okay = false;
foreach($checks as $check)
{
$tmp = explode(':', $check);
if ('DNS' != $tmp[0]) continue; // candidates must start with DNS:
if (!isset($tmp[1])) continue; // and have something afterwards
$tmp = explode('.', $tmp[1]);
if (count($tmp) < 3) continue; // "*.com" is not a valid match
$cand = array_reverse($tmp);
$okay = true;
foreach($cand as $i => $item)
{
if (!isset($fles[$i]))
{
// We connected to www.example.com and certificate is for *.www.example.com -- bad.
$okay = false;
break;
}
if ($fles[$i] == $item)
continue;
if ($item == '*')
break;
}
if ($okay)
break;
}
if (!$okay)
$secure = false; // No hosts matched our server.
}
if (!$secure)
die("failed to connect securely\n");
print "Success!\n";
// Continue with connection...
?>
The push works just fine, the problem is that the feedback is empty. I need to delete the tokens that have expired or have an invalid status.This is what I write test code,this a problem?]
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
$fp = stream_socket_client('ssl://feedback.sandbox.push.apple.com:2196', $error, $errorString, 60, STREAM_CLIENT_CONNECT, $ctx);
if (!$fp) {
return;
}
while ($devcon = fread($fp,38)) {
$arr = unpack("H*", $devcon);
$rawhex = trim(implode("", $arr));
$feedbackTime = hexdec(substr($rawhex, 0, 8));
$feedbackDate = date('Y-m-d H:i', $feedbackTime);
$feedbackLen = hexdec(substr($rawhex, 8, 4));
$feedbackDeviceToken = substr($rawhex, 12, 64);
}
fclose($fp);
Feedback services don't always return data. You will get data only if there is need to report failed deliveries.
See the documentation here.
Not sure if this is true but I have noticed feedback services don't work with the sandbox environment (at least I haven't received a response any time I checked with sandbox)
I am new in a php and write a code for push notification in codeigniter but I got these erros.
Here is my model..
function sendmessage($appid, $deviceid, $status, $message)
{
$deviceToken = '0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78';
$message = 'My first push notification!';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
//stream_context_set_option($ctx, 'ssl', 'passphrase', 'essar#123');
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if (!$fp){
exit("Failed to connect: $err $errstr" . PHP_EOL);
}
else {
print "Connection OK/n";
}
echo 'Connected to APNS' . PHP_EOL;
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
$payload = json_encode($body);
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
fclose($fp);
$data = array(
'message' => $this->message . 'add',
'appid' => $this->appid,
'deviceid' => $this->deviceid,
'status' => $status
);
$this->sendmessage($data);
Error message:
Message: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure Message: stream_socket_client(): Failed to enable crypto Message: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Unknown error)
Once you created the provisional certificates and push notification for both development and distribution. Follow the steps for Generate Push Notification
In order to use the certificates you generated, you need to create a PEM file that stores both, your Apple Push Notification Service SSL Certificate and your Private Key. You can create the PEM file from a terminal.
Navigate to the directory that contains the certificates and key you generated earlier and execute the following steps. The file names here reflect the names of the certificates that were generated as part of this lesson. You have to update the syntax according the names you gave your certificates.
First create the application certificate PEM file. You can do this by double clicking on the aps_developer_identity.cer certificate file, then opening the Keychain Assistant and exporting the certificate as ap12 file and then converting it to a PEM file, in the same fashion as the PushNotificationApp.p12 is converted to a PEM file. Alternatively you can use a single command line that converts the aps_developer_identity.cer certificate file directly to a PEM file. Here we are opting for the single command line option, as follows:
openssl x509 -inform der -outform pem -in aps_developer_identity.cer -out PushNotificationAppCertificate.pem
Now create the application key PEM file as follows. You need to enter the import password and PEM pass phrase:
openssl pkcs12 -in PushNotificationApp.p12 -out PushNotificationAppKey.pem -nocerts
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Now concatenate the two files:
cat PushNotificationAppCertificate.pem PushNotificationAppKey.pem > PushNotificationAppCertificateKey.pem
Open a Mac terminal and execute the following line from the directory that contains the certificates you generated:
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushNotificationAppCertificate.pem -key PushNotificationAppKey.pem
You are then asked to enter the pass phrase for the key you submitted:
Enter pass phrase for PushNotificationAppKey.pem:
If everything worked, then the server should send you a lot of information that may look something like the following:
CONNECTED(00000003)
depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
verify error:num=20:unable to get local issuer certificate verify return:0
...
Key-Arg : None
Start Time: 1326899631 Timeout : 300 (sec) Verify return code: 0 (ok)
At the end of this, you can enter some text and then select the return key. We entered the text "**Hello World**".
**Hello World
closed**
This completes the communication with the server and verifies that our certificates work.
I have been having the same issue as you mentioned here. This took some time and head scratching to find...
The solution that I found that corrected the handshake error was to download the entrust certificate, and include this in the stream context using the code below:
$entrustCert = '<full path to cert>/entrust_2048_ca.cer';
stream_context_set_option($ctx, 'ssl', 'cafile', entrustCert);
There does seem to intermittent connection issues with the sandbox APN service. I occasionally get errors returned like:
Warning: stream_socket_client(): SSL: Connection reset by peer
Warning: stream_socket_client(): Failed to enable crypto
I hope this is a time saver for someone!
function send_iOS_notifications($device_tokens, $notification_content)
{
$this->load->library('apn');
$this->apn->payloadMethod = 'enhance'; // you can turn on this method for debuggin purpose
$this->apn->connectToPush();
//$badge_count = $this->set_and_get_ios_active_notifications('',$device_token);
// adding custom variables to the notification
$this->apn->setData($notification_content);
$message = $notification_content['message'];
if ((strpos($message, 'http://') !== false) || (strpos($message, 'https://') !== false)) {
$message = "Image";
}
//$send_result = $this->apn->sendMessage($device_token, 'Test notif #1 (TIME:'.date('H:i:s').')', /*badge*/ 2, /*sound*/ 'default' );
$send_result = $this->apn->sendMessage($device_tokens, $message, /*badge*/ '', /*sound*/ 'default' );
if($send_result){
log_message('debug','Sending successful');
$result['status'] = true;
$result['message'] = 'Sending successful';
}
else{
log_message('error',$this->apn->error);
$result['status'] = true;
$result['message'] = $this->apn->error;
}
$this->apn->disconnectPush();
}
I'm sending push notifications and when the message contains foreign characters (Turkish in my case) like İ, ş, ç, ğ... The message does not arrive to devices.
Here's my code:
$message = 'THİS is push';
$passphrase = 'mypass';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'MyPemFile.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to Apple service. ' . PHP_EOL;
// Encode the payload as JSON
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
$payload = json_encode($body);
$result = 'Start'.PHP_EOL;
$tokenArray = array('mytoken');
foreach ($tokenArray as $item)
{
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $item) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Failed message'.PHP_EOL;
else
echo 'Successful message'.PHP_EOL;
}
// Close the connection to the server
fclose($fp);
I have tried encoding $message variable with utf8_encode() but the message received as "THÝS is push". And other ways like iconv() didn't work for me, some of them cropped Turkish characters, some didn't receive at all.
I also have
header('content-type: text/html; charset: utf-8');
and
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
in my page. I don't think the problem appears while I set the value but maybe with pack() function.
Any ideas to solve this without replacing characters with English?
All I had to do was replacing the Turkish characters with following script:
function tr_to_utf($text) {
$text = trim($text);
$search = array('Ü','Ş','Ğ','Ç','İ','Ö','ü','ş','ğ','ç','ı','ö');
$replace = array('Ãœ','Å','Ğ','Ç','Ä°','Ö','ü','ÅŸ','ÄŸ','ç','ı','ö');
$new_text = str_replace($search,$replace,$text);
return $new_text;
}
Now it is working with no problems.
This is the source.
The "n" parameter means, that you pack as unsigned short (always 16 bit, big endian byte order). I`m not sure how Apple CPU hardware handle the instructions and how convert them, but is different from the PC for sure. Try to switch the byte order, use "v" unsigned short (always 16 bit, little endian byte order).