Re: [strongSwan] Strongswan 4.2.14 broken on ARM ?
> I've removed any reads to unaligned integers in the parser code [1], generator looks OK so far. I don't have an ARM box, so any feedback is very welcome. > > Thanks > Martin > > [1]http://wiki.strongswan.org/repositories/diff/strongswan?rev=42748858 > > Martin, Thanks for that patch. With a small bit of adjustment, I managed to apply the patch to my copy of the 4.2.14 code, :-), and rebuild. It seems to work fine, so far. I did have a small problem the first time I brought the ARM up, in that the initial SA came up fine but then something started creating LOTS of child SAs. I pulled the plug on the ARM box after we got to 100 child SAs. Unfortunately, I did not have any charon logging turned on, so had no logs to comb through. Since then, restarting the ARM box and bringing up the connection has exhibited no problems (and no unwanted child SAs). So, looking good (but feeling slightly nervous about it needing wider testing). Regards, Graham. ___ Users mailing list Users@lists.strongswan.org https://lists.strongswan.org/mailman/listinfo/users
Re: [strongSwan] Strongswan 4.2.14 broken on ARM ?
Hi, > Whenever the byte in memory is half-word-aligned, reading it as a uint16 > works as expected. The other half of the time, the compiler is adjusting > the pointer (back one) to make it half-word-aligned before reading the two > bytes as a uint16. Yes, it seems that some ARM CPUs don't like unaligned (half-)word reads. > I can find at least 26 occasions in the strongSwan code where this > reading-a-byte-pointer-as-a-uint16-pointer idiom occurs. I think not all of them are problematic. GCC should align struct members properly, so read/write to struct members shouldn't be a problem (except __packed__ ones, I'll review those). I've removed any reads to unaligned integers in the parser code [1], generator looks OK so far. I don't have an ARM box, so any feedback is very welcome. Thanks Martin [1]http://wiki.strongswan.org/repositories/diff/strongswan?rev=42748858 ___ Users mailing list Users@lists.strongswan.org https://lists.strongswan.org/mailman/listinfo/users
Re: [strongSwan] Strongswan 4.2.14 broken on ARM ?
> Hi, > > I wonder if anyone can please help me with a problem I'm having getting > strongSwan (4.2.14) running on the ARM ? > > I've played about getting strongSwan working on x86 setting up a tunnel to > a server. I then compiled strongSwan for ARM and copied across the config > files I used on x86. > > The ARM version fails to set up the tunnel. > I hate replying to my own email, but I've been playing around with the ARM compiler. > > Can anyone explain this and how to fix it easily ? > It seems that there is a word (or, half-word) alignment thing going on here. I've written another test program which iterates through the array of 6 bytes, converting each one to a uint16. The array is: 0x27, 0xff, 0x03, 0xFA, 0x04, 0x30 On the x86, the output is: => 0x27ff bytes = 0xbfc8bffe, byte_pos = 0xbfc8bffe, &bytes[0] = 0xbfc8bffe *byte_pos = 0x27 *((u_int16_t*) byte_pos) = 65319 = 0xff27 ntohs(*((u_int16_t*) byte_pos)) = 10239 = 0x27ff => 0xff03 bytes = 0xbfc8bffe, byte_pos = 0xbfc8bfff, &bytes[1] = 0xbfc8bfff *byte_pos = 0xff *((u_int16_t*) byte_pos) = 1023 = 0x03ff ntohs(*((u_int16_t*) byte_pos)) = 65283 = 0xff03 => 0x03fa bytes = 0xbfc8bffe, byte_pos = 0xbfc8c000, &bytes[2] = 0xbfc8c000 *byte_pos = 0x03 *((u_int16_t*) byte_pos) = 64003 = 0xfa03 ntohs(*((u_int16_t*) byte_pos)) = 1018 = 0x03fa => 0xfa04 bytes = 0xbfc8bffe, byte_pos = 0xbfc8c001, &bytes[3] = 0xbfc8c001 *byte_pos = 0xfa *((u_int16_t*) byte_pos) = 1274 = 0x04fa ntohs(*((u_int16_t*) byte_pos)) = 64004 = 0xfa04 => 0x0430 bytes = 0xbfc8bffe, byte_pos = 0xbfc8c002, &bytes[4] = 0xbfc8c002 *byte_pos = 0x04 *((u_int16_t*) byte_pos) = 12292 = 0x3004 ntohs(*((u_int16_t*) byte_pos)) = 1072 = 0x0430 You can see that the bytes are bring read correctly (e.g. 0x27ff, 0xff03, 0x03fa, etc.). On the ARM, the output is: => 0xe427 bytes = 0xbedcebfd, byte_pos = 0xbedcebfd, &bytes[0] = 0xbedcebfd *byte_pos = 0x27 *((u_int16_t*) byte_pos) = 10212 = 0x27e4 ntohs(*((u_int16_t*) byte_pos)) = 58407 = 0xe427 => 0xff03 bytes = 0xbedcebfd, byte_pos = 0xbedcebfe, &bytes[1] = 0xbedcebfe *byte_pos = 0xff *((u_int16_t*) byte_pos) = 1023 = 0x03ff ntohs(*((u_int16_t*) byte_pos)) = 65283 = 0xff03 => 0xff03 bytes = 0xbedcebfd, byte_pos = 0xbedcebff, &bytes[2] = 0xbedcebff *byte_pos = 0x03 *((u_int16_t*) byte_pos) = 1023 = 0x03ff ntohs(*((u_int16_t*) byte_pos)) = 65283 = 0xff03 => 0xfa04 bytes = 0xbedcebfd, byte_pos = 0xbedcec00, &bytes[3] = 0xbedcec00 *byte_pos = 0xfa *((u_int16_t*) byte_pos) = 1274 = 0x04fa ntohs(*((u_int16_t*) byte_pos)) = 64004 = 0xfa04 => 0xfa04 bytes = 0xbedcebfd, byte_pos = 0xbedcec01, &bytes[4] = 0xbedcec01 *byte_pos = 0x04 *((u_int16_t*) byte_pos) = 1274 = 0x04fa ntohs(*((u_int16_t*) byte_pos)) = 64004 = 0xfa04 Which is plain wrong. Whenever the byte in memory is half-word-aligned, reading it as a uint16 works as expected. The other half of the time, the compiler is adjusting the pointer (back one) to make it half-word-aligned before reading the two bytes as a uint16. I can find at least 26 occasions in the strongSwan code where this reading-a-byte-pointer-as-a-uint16-pointer idiom occurs. I have not searched for the byte-pointer->uint32-pointer case yet :-( Graham. #include #include #define MORE_TRACING int main() { u_int8_t bytes[] = { 0x27, 0xff, 0x03, 0xFA, 0x04, 0x30 }; u_int8_t bit_pos; u_int8_t* byte_pos; byte_pos = bytes; int i; for(i = 0; i < 5; ++i) { u_int16_t output_pos; // u_int16_t intermediate = *(byte_pos + 1) << 8 | *(byte_pos + 0); // output_pos = ntohs(intermediate); output_pos = ntohs(*((u_int16_t*) byte_pos)); printf(" => 0x%04x\n", output_pos); #ifdef MORE_TRACING printf("\tbytes = 0x%x, byte_pos = 0x%x, &bytes[%d] = 0x%x\n", (unsigned int) bytes, (unsigned int) byte_pos, i, (unsigned int) &bytes[i]); printf("\t*byte_pos = 0x%02x\n", *byte_pos); printf("\t*((u_int16_t*) byte_pos) = %d = 0x%04x\n", *((u_int16_t*) byte_pos), *((u_int16_t*) byte_pos)); printf("\tntohs(*((u_int16_t*) byte_pos)) = %d = 0x%04x\n", ntohs(*((u_int16_t*) byte_pos)), ntohs(*((u_int16_t*) byte_pos))); printf("\n\n"); #endif /* MORE_TRACING */ byte_pos++; } return 0; }___ Users mailing list Users@lists.strongswan.org https://lists.strongswan.org/mailman/listinfo/users
[strongSwan] Strongswan 4.2.14 broken on ARM ?
Hi, I wonder if anyone can please help me with a problem I'm having getting strongSwan (4.2.14) running on the ARM ? I've played about getting strongSwan working on x86 setting up a tunnel to a server. I then compiled strongSwan for ARM and copied across the config files I used on x86. The ARM version fails to set up the tunnel. Turning on tracing to level 3 everywhere gets me the following line in the client (left?) /var/log/messages: charon: 08[MGR] checkout IKE_SA charon: 13[ENC] parsing rule 0 U_INT_8 charon: 13[ENC]=> 39 charon: 13[ENC] parsing rule 1 FLAG charon: 13[ENC]=> 0 charon: 13[ENC] parsing rule 2 RESERVED_BIT charon: 13[ENC] parsing rule 3 RESERVED_BIT charon: 13[ENC] parsing rule 4 RESERVED_BIT charon: 13[ENC] parsing rule 5 RESERVED_BIT charon: 13[ENC] parsing rule 6 RESERVED_BIT charon: 13[ENC] parsing rule 7 RESERVED_BIT charon: 13[ENC] parsing rule 8 RESERVED_BIT charon: 13[ENC] parsing rule 9 PAYLOAD_LENGTH charon: 13[ENC]=> 3 charon: 13[ENC] encrypted payload could not be decrypted and parsed charon: 13[ENC] could not decrypt payloads charon: 13[IKE] IKE_AUTH response with message ID 1 processing failed The client is trying to use ike=aes128-sha-modp1024!, esp=aes128-sha1, 3des-md5 and EAP-SIM. The client has sent out the initial IKE_SA_INIT request and been happy with the IKE_SA_INIT response. The client has then sent out the first IKE_AUTH request and has then had trouble processing the first IKE_AUTH response. Working back from the "encrypted payload could not be decrypted and parsed" error in the code, I can see that message.c:decrypt_payloads() has managed to decrypt and parse one payload (the ID_RESPONDER one) and has started on the CERTIFICATE payload. The code manages to decrypt this payload okay and starts to parse it (see parser.c:parse_payload()). The payload starts with the following bytes: 0x27, 0x00, 0x03, 0xFA, 0x04, 0x30 On the x86, the code parses the first byte as one uint_8 = 39 decimal (27 hex), 8 1-bit fields and a uint_16 payload-length = 1018 decimal (03FA hex). On the ARM, the code parses the first byte as one uint_8 = 39 (decimal), 8 1-bit fields and a uint_16 payload-length = 3 decimal (0003 hex) !! The code, rightly, thinks this is rubbish and fails the rest of the parse. I've worked my way through the code in parser.c (e.g. parse_payload(), parse_uint8(), parse_bit() and parse_uint16()) and managed to reduce them to a small test program (hopefully attached). If I compile and run this on the x86, I get: parsing rule 0 U_INT_8 => 39 skipping rules 1 FLAG ... 8 RESERVED_BIT parsing rule 9 PAYLOAD_LENGTH => 1018 output. On the ARM, I get: parsing rule 0 U_INT_8 => 39 skipping rules 1 FLAG ... 8 RESERVED_BIT parsing rule 9 PAYLOAD_LENGTH => 65283 To make things more clear what it going on, I have changed the second byte of the message from 0x00 to 0xff in my test program. If I replace the line: output_pos = ntohs(*((u_int16_t*) byte_pos)); by: u_int16_t intermediate = *(byte_pos + 1) << 8 | *(byte_pos + 0); output_pos = ntohs(intermediate); everything works as expected on both x86 and ARM. Also found that something like the following works on both x86 and ARM: u_int16_t intermediate; u_int8_t* intermediate_bytes = (u_int8_t*) &intermediate; intermediate_bytes[0] = byte_pos[0]; intermediate_bytes[1] = byte_pos[1]; output_pos = ntohs(intermediate); Can anyone explain this and how to fix it easily ? I'm hoping that someone will say that this is fixed by a command-line flag on the ARM version of gcc ;-} Version of ARM gcc in use is 4.1.1. If this does mean a strongSwan code fix, will it just be to parse_uint16() ? Or parse_uint32() too ? Or is this idiom endemic throughout the strongSwan code ? Thanks for any help, Graham. #include #include int main() { u_int8_t bytes[] = { 0x27, 0xff, 0x03, 0xFA, 0x04, 0x30 }; u_int8_t bit_pos; u_int8_t* byte_pos; byte_pos = bytes; printf(" parsing rule 0 U_INT_8\n"); { u_int8_t output_pos; output_pos = *(byte_pos); printf(" => %d\n", output_pos); } byte_pos++; printf(" skipping rules 1 FLAG ... 8 RESERVED_BIT\n"); byte_pos++; printf(" parsing rule 9 PAYLOAD_LENGTH\n"); { u_int16_t output_pos; // u_int16_t intermediate = *(byte_pos + 1) << 8 | *(byte_pos + 0); // output_pos = ntohs(intermediate); output_pos = ntohs(*((u_int16_t*) byte_pos)); printf(" => %d\n", output_pos); #ifdef MORE_TRACING printf("bytes = 0x%x, byte_pos = 0x%x, bytes + 2 = 0x%x\n", (unsigned int) bytes, (unsigned int) byte_pos, (unsigned int) (bytes + 2)); printf("*byte_pos = %d\n", *byte_pos); printf("*((u_int16_t*) byte_pos) = %d = 0x%x\n", *((u_int16_t*) byte_pos), *((u_int16_t*) byte_pos)); printf