Today I sent a message to the Muscle list, that said:

> The situation I was running into is with the ccid-1.3.13/src/commands.c
> The SecurePINVerify routine takes a TxBuffer described in PCSC part10 section
> 2.5.2 PIN_VERIFY. Section 2.5.1 say the structures in section 2.5 will be:
> "Byte ordering is decided by machine architecture". The routine then copies
> parts of the PIN_VERIFY to what USB CCID describes in section 6.1.11.2 "PIN
> Verification Data Structure"  This needs to use little endian. No conversion
> from machine to CCID ordering is done during the copy.
>
> The problem is the SecurePINVerify is expecting the caller to provide the
> wPINMaxExtraDigit, wLangid and ulDataLength in little endian.
>
> The way I read pcsc part 10 is that wPINMaxExtraDigit, wLangid and 
> ulDataLength
> and any other USHORT or ULONG in any of the structures in 2.5 should be passed
> in machine order, and the SecurePINVerify while copying these fields should do
> the byte ordering conversion. The caller to SecurePINVerify should not be 
> doing this.
>
> The way I ran into this is the OpenSC was not doing the conversion correctly,
> (and it should not have had to do it at all.) This situation only fails on big
> endian machine trying to use a PIN Pad reader.

So I think the problem is in both the CCID and OpenSC. The ulDataLength
and the wPINMaxExtraDigit and wLangId should all be in host byte order.
OpenSC should not be using the HOST_TO_CCID at all,
and the SecurePINVerify routing should be converting the fields as they
are copied to the cmd[] to be sent.



On 7/29/2010 1:40 PM, Ludovic Rousseau wrote:
> 2010/7/27 Douglas E. Engert<[email protected]>:
>> On a Solaris 10 sparc machine, using pcsc and opensc both from
>> svn, there appears to be a mismatch of handing the length
>> field within the message for using a pin pad reader.
>>
>> pcscd trace shows:
>>
>> 00000126 ../../src/src/ifdhandler.c:1307:IFDHControl() ControlCode: 
>> 0x42330006, usb:076b/3821:libusb:/dev/usb:76b.
>> 3821/0 (lun: 0)
>> 00000068 Control TxBuffer: 1E 1E 02 08 00 04 08 02 FF 00 00 00 00 00 00 00 
>> 00 00 0D 00 20 00 80 08 FF FF FF FF FF
>> FF FF FF
>> 00000636 ../../src/src/commands.c:312:SecurePINVerify() Wrong lengths: 
>> 218103827 32
>> 00000055 Control RxBuffer:
>> 00000049 ../../src/src/ifdwrapper.c:644:IFDControl() Card not transacted: 614
>>
>> This comes down to: 218103827 = 0x0D000013
>> as the test in ccid commands.c is testing:
>>   if (dw2i(TxBuffer, 15) + 19 != TxLength)
>> which if it was stored as 0D 00 00 00, dw2i would have converted it to
>>   13+19=32, and the length would have been correct.
>>
>> OpenSC internal-winscard.h  appears to be where the problem is:
>> #define HOST_TO_CCID_16(x) (x)
>> #define HOST_TO_CCID_32(x) (x)
>>
>> Where as PCSC/reader.h has:
>> #define HOST_TO_CCID_16(x) ((((x)>>  8)&  0xFF) + ((x&  0xFF)<<  8))
>> #define HOST_TO_CCID_32(x) ((((x)>>  24)&  0xFF) + (((x)>>  8)&  0xFF00) + 
>> ((x&  0xFF00)<<  8) + (((x)&  0xFF)<<
>> 24))
>>
>> and PCSC has in "configure.in" tests for bigendian using:
>>
>>   # HOST_TO_CCID
>>   if test "x$ac_cv_c_bigendian" = "xyes"; then
>>       AC_SUBST(host_to_ccid_16, ['((((x)>>  8)&  0xFF) + ((x&  0xFF)<<  
>> 8))'])
>>       AC_SUBST(host_to_ccid_32, ['((((x)>>  24)&  0xFF) + (((x)>>  8)&  
>> 0xFF00    ) + ((x&  0xFF00)<<  8) + (((x
>> )&  0xFF)<<  24))'])
>>       AC_MSG_RESULT([plateform endianess           : big endian])
>>   else
>>       AC_SUBST(host_to_ccid_16, ['(x)'])
>>       AC_SUBST(host_to_ccid_32, ['(x)'])
>>       AC_MSG_RESULT([plateform endianess           : little endian])
>>   fi
>>
>>
>> It looks like OpenSC need to test for bigendian.
>
> Yes.
>
> You can either test:
> - at configure time: easy and not need to define a define
> - at compilation time: if you generate a binary for little and big
> endian from the same source code
>
> For example reader.h on Mac OS X contains:
>
> /** the wLangId and wPINMaxExtraDigit are 16-bits long so are subject to byte
>   * ordering */
> #ifdef __BIG_ENDIAN__
> #define HOST_TO_CCID_16(x) ((((x)>>  8)&  0xFF) + ((x&  0xFF)<<  8))
> #define HOST_TO_CCID_32(x) ((((x)>>  24)&  0xFF) + (((x)>>  8)&
> 0xFF00) + ((x&  0xFF00)<<  8) + (((x)&  0xFF)<<  24))
> #else
> #define HOST_TO_CCID_16(x) (x)
> #define HOST_TO_CCID_32(x) (x)
> #endif
>
> It does work because __BIG_ENDIAN__ is always defined on big endian
> Mac computers.
> And this is needed because gcc on Mac OS X generates code for Motorola
> PowerPC (big endian) and Intel i386 or x86_64 (little endian).
>
> Does the compiler on Solaris also defines __BIG_ENDIAN__ where needed?

The issue was the OpenSC code did not use the PCSC/readeri.h, but
used the OpenSC internal-reader.h where it just defined

#define HOST_TO_CCID_16(x) (x)
#define HOST_TO_CCID_32(x) (x)

But as I supgest above, if the conversion should be done in CCID, then
HOST_TO_* are not needed in any application including OpenSC.


>
>> (On the Muscle list there is a discussion of size of DWORD, and since the
>> SecurePINVerify is using dw2i() assuming 32 bit number,
>> this might also cause an error on a 64 bit machine trying to use a
>> pin pad reader.)
>
> I don't see a problem here.
> dw2i() assumes a 32-bit number but the value to convert is also
> 32-bits even on 64-bits systems.

Correct this is not a problem.

>
> Maybe you can show me a counter example?
>
> Bye
>

-- 

  Douglas E. Engert  <[email protected]>
  Argonne National Laboratory
  9700 South Cass Avenue
  Argonne, Illinois  60439
  (630) 252-5444
_______________________________________________
opensc-devel mailing list
[email protected]
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to