clausecker / nfc

Go bindings for the libnfc
https://pkg.go.dev/github.com/clausecker/nfc/v2
GNU Lesser General Public License v3.0
101 stars 20 forks source link

ISO14443aTarget marshalling problem? #4

Closed messinm closed 9 years ago

messinm commented 9 years ago

See https://gist.github.com/messinm/7086bfce591bf6f1d554 Running under Ubuntu 14.04 64-bit, libnfc 1.7.0

mifare target gives the following from printing Target received from InitiatorListPassiveTargets: ISO/IEC 14443A (106 kbps) target: ATQA (SENS_RES): 00 04

Fingerprinting based on MIFARE type Identification Procedure:

Then attempting marshalling to ISO14443aTarget, I get the following:

Atqa =[0 4] Sak =8 UIDLen =33091718999965696 UID =[112 70 188 32 255 0 0 0 0 0] Note that 33091718999965696 = 0x7590BE3C000000, so it appears that the UIDLen field actually contains the UID.

Am I doing something wrong in the marshalling code? Or is this a bug in Go NFC lib or libnfc?

clausecker commented 9 years ago

Sounds like a bug in my code to me. Let me check please.

clausecker commented 9 years ago
unsafe_p := (unsafe.Pointer(targets[0].Marshall()))
defer C.free(unsafe_p)
mtarget := (*nfc.ISO14443aTarget)(unsafe_p)

Casting an unsafe.Pointer you get from Marshall() to one of the target types can't work. The pointer you get from Marshall() points to a C type, whereas the target types are entirely different types. As per documentation for Target.Marshall():

Marshall() returns a pointer to an nfc_target allocated with C.malloc() that contains the same data as the Target. Don't forget to C.free() the result of Marshall() afterwards. A runtime panic may occur if any slice referenced by a Target has been made larger than the maximum length mentioned in the respective comments.

Where nfc_target refers to the C type nfc_target, not the Go type. If you want to convert a Target into an object of concrete type, use a type assertion like this (replacing the code above):

mtarget, ok := targets[0].(nfc.ISO14443aTarget)
if !ok {
    // targets[0] is apparently not an ISO 14443a target. Do something here...
}

Please tell me if this solved your problem and then close the issue.

messinm commented 9 years ago

Thanks for the quick response.

I tried your suggestion, but it won't compile. See snippet and error message below. Seems that nfc.ISO14443aTarget should implement nfc.Target, but doesn't.

                            //unsafe_p := (unsafe.Pointer(targets[0].Marshall()))
                            //defer C.free(unsafe_p)
                            //mtarget := (*nfc.ISO14443aTarget)(unsafe_p) 

                            mtarget, ok := targets[0].(nfc.ISO14443aTarget)
                            if !ok {
                               fmt.Printf("Not ISO14443aTarget!")
                            } else {
            fmt.Printf("Atqa =%v\n",mtarget.Atqa)
            fmt.Printf("Sak =%v\n",mtarget.Sak) 
                    fmt.Printf("UIDLen =%v\n",mtarget.UIDLen)  
                    fmt.Printf("UID =%v\n",mtarget.UID) 
                            }

//does not compile: //../src/messinm2/testnfc/testnfc.go:81: impossible type assertion: // nfc.ISO14443aTarget does not implement nfc.Target (Marshall method has pointer receiver)

clausecker commented 9 years ago

Sorry. Cast to *nfc.ISO14443aTarget, not nfc.ISO14443aTarget. I don't know why I forgot that star.

messinm commented 9 years ago

That works! Thanks, and thanks very much for the lib.

clausecker commented 9 years ago

It was a pleasure to me.