# Poynt Device Object Signing
Poynt Terminal Object Signing process requires the Terminal to be able to generate and use an RSA 2048 Key Pair. The Terminal’s RSA Key Pair is used as the Device Signing Key in the Poynt Remote Key Loading Process to load processor/acquirer keys into the Terminal over secure network connection.
The following diagram outlines the overall process flow of the Object Signing Process. The Object Signing Tool (or its equivalent) must enforce a ‘DUAL Login’ requirement and establish a secure mutual SSL connection with Poynt Cloud.
- Using dual login, admin initiates generation of Certificate Signing Request (CSR) on the device. The device generates a RSA 2048 key pair, saves the private key in the NVSRAM (secure memory) and craft a CSR containing the public key that is sent to RKMS server for signing
- The subject of the CSR must be the serial number of the terminal.
- RKMS server generates Device Signing Certificate (DSC) from CSR and sends it to device
- DSC is saved on device's external flash.
- Root CA is hardcoded in firmware, and up to 10 sub certificates are loaded into the device. These certificates will be used to verify the RKMS signing and encrypting certificates that are exchanged at the beginning of the remote key injection process
# Prerequisites
Devices must support secure generation of RSA keypair and storing in secure memory.
Poynt Root CA certificates for LIVE and TEST must be bundled in code. Only the LIVE root certificate must be used when the card reader is in LIVE (PCI) mode. TEST root certificate must only be used when the card reader is in unlocked (non-PCI) mode for testing.
If Devices are not capable of generating RSA keypair, then an external system could be used to generate and securely load into the Terminal. But the external system must pass the PCI requirements similar to any key loading devices (KLD).
# Object Signing APIs
Following are the APIs that must be provided by the card reader to support the Object Signing process. These APIs are defined as part of the IPoyntPaymentSecuritySPI.aidl and must be implemented to support terminal object signing. Please refer to "PoyntOSVendorSDK" for actual methods and callback references.
# getDeviceCSR()
This method is used to retrieve a certificate signing request for the terminal, which is used to send to Poynt Object Signing service and signed by Poynt CA.
# Input Params
Device serial -- serial number of the device being object signed as a string
- Eg. P6SW371JS027592
Callback - where the CSR is returned or an error message if failed to generate CSR. Following are the 2 methods defined in the callback.
onResponse(String certificate)
onError(PoyntError error)
# Output Params
Upon receiving this request, PaymentSecuritySPI service must validate the device serial number, generate RSA 2048 keypair, and generate CSR with device serial number as cname. The CSR should be returned to the caller through the callback in PKCS#10 format and DER Encoded. Note all binary values (bytes[]) are always encoded as hex strings without "0x" prefixes.
Please refer to Appendix for sample CSR and command line tools to verify.
# Error conditions
If a terminal is already object signed, return error
a. PoyntError.DEVICE_ALREADY_OBJECT_SIGNED
If RSA key pair generation failed, return error.
a. PoyntError.DEVICE_RSA_KEYPAIR_GENERATION_FAILED
If the serial number provided doesn't match the serial number of the card reader, return error.
a. PoyntError.DEVICE_INVALID_SERIAL
If CSR generation failed, return
a. PoyntError.DEVICE_CSR_GENERATION_FAILED
# setDeviceSigningCertificate()
This method is used to load a signed Device Signing Certificate into the card reader. The CSR obtained through the getDeviceCSR() is sent to Poynt Cloud and signed by Poynt Root CA. Once it's signed, it's loaded back into the card reader for the terminal to be able to use during the remote key loading process.
# Input Params
Device Certificate - DER encoded signed X509 Cert. Note that the value is a hex encoded string of the certificate.
Callback - where the result of the loading operation is returned. Following are the 2 methods defined in the callback.
onSuccess()
onError(PoyntError error)
# Output Params
Upon receiving the request with a signed X509 Certificate, card reader must validate the certificate to ensure it matches the device signing key pair. When the certificate is validated and saved, the onSuccess() callback must be called.
# Error Conditions
If a certificate is already loaded, return error.
a. PoyntError.DEVICE_ALREADY_OBJECT_SIGNED
If the keypair corresponding to the certificate being loaded is not found, return error.
a. PoyntError.DEVICE_SIGNING_KEYPAIR_NOT_FOUND
If the certificate is invalid or in incorrect format, return error
a. PoyntError.DEVICE_INVALID_SIGNING_CERT
If saving device signing certificate failed, then return
a. PoyntError.DEVICE_LOAD_SIGNING_CERT_FAILED
# loadTrustedSourceCertificate()
This method is used to load all the CA certificates in the trusted CA chain used for validating the certificates of the Terminal and remote RKMS system during remote key injection process. This method is called multiple times to load all the necessary CA certificates in the trusted CA chain.
# Input Params
Device Certificate - DER encoded signed X509 Cert. Note that the value is a hex encoded string of the certificate.
Callback - where the result of the loading operation is returned. Following are the 2 methods defined in the callback.
onSuccess()
onError(PoyntError error)
# Output Params
Upon receiving the request with a signed X509 Certificate, the card reader must validate the certificate to ensure it's a value X509 Cert. When the certificate is validated and saved, the onSuccess() callback must be called.
# Error Conditions
If the certificate is already loaded (same signature, serial, hash), return success. If not overwrite.
If the certificate is invalid or in incorrect format, return error.
a. PoyntError.DEVICE_INVALID_TRUSTED_CERT
If cert load failed, return error
a. PoyntError.LOAD_TRUSTED_CERT_FAILED
# getDeviceSigningCertificate()
This method is used to retrieve the terminal's signing certificate. This certificate is loaded as part of the setDeviceSigningCertificate() method during the Object Signing Process.
# Input Params
Callback - where the device certificate is returned or an error if device certificate is not found.
onResponse(String certificate)
onError(PoyntError error)
# Output Params
Returns the signed device signing certificate loaded during the Object Signing process using the onResponse() callback. On error the corresponding error is returned using the onError() callback. Returned certificate is a DER encoded signed X509 Cert as hex encoded string.
# Error Conditions
If there is no device signing certificate, return error.
- PoyntError.DEVICE_SIGNING_CERT_NOT_FOUND
# getDeviceCertificatesStatus()
This method returns the status indicating the presence of various certificates loaded during the Object Signing process and are used for Remote Key Loading.
# Input Params
Callback - where the device certificate status is returned or an error if device certificate is not found.
onSuccess(String summary)
onError(PoyntError error)
# Output Params
Returns certificate status summary as a 16 byte array where each byte represents the status of a certificate.
00h when the related certificate is not present, or
01h when the related certificate is present.
Mapping of each of the byte to certificates is as follows:
· Byte 0: Pre-Loaded Root Certificate
· Byte 1-10: Trusted Non-Root Certificates
· Byte 11: Working RKMS Signing Certificate sent during the RKL process
· Byte 12: Working RKMS Encryption Certificate sent during the RKL process
· Byte 13: RFU
· Byte 14: RFU
· Byte 15: Device Signing Certificate
# Error Conditions
If the device is not capable of remote key loading, return error.
- PoyntError.DEVICE_CERTS_NOT_FOUND
If no certificates are found, return onSuccess call back with the summary set as defined above.
# getDeviceTrustedCertificatesSummary()
This method returns an ASCII string that represents the summary of all certificates in the chain of trust.
# Input Params
Callback - where the device trusted certificates summary is returned or an error if device trusted certificates are not found.
onSuccess(String summary)
onError(PoyntError error)
# Output Params
ASCII String containing summary of certs starting from the end of the chain to the root is returned as summary in the onSuccess() callback. Note that the format of every certificate summary is the same containing information about the issuer, subject, issued on, expires on, signature algorithm used and the RSA key size -- in that specific order.
Eg.
ISSUER:CN=RKL SubCA, emailAddress=support@poynt.com
SUBJECT:CN=Loader RKL SubCA, emailAddress=support@poynt.com
ISSUED:2016-01-21 00:00:00
EXPIRES:2049-01-21 00:00:00
SIGNATURE: RSA with SHA-256
RSA key size :2048
ISSUER:CN=Poynt-SubRoot, emailAddress=support@poynt.com
SUBJECT:CN=RKL SubCA, emailAddress=support@poynt.com
ISSUED:2016-01-21 00:00:00
EXPIRES:2049-01-21 00:00:00
SIGNATURE: RSA with SHA-256
RSA key size :2048
ISSUER:CN=Poynt-Root, emailAddress=support@poynt.com
SUBJECT:CN=Poynt-SubRoot, emailAddress=support@poynt.com
ISSUED:2016-01-19 00:00:00
EXPIRES:2050-01-19 00:00:00
SIGNATURE: RSA with SHA-256
RSA key size :2048
ISSUER:CN=Poynt-Root, emailAddress=support@poynt.com
SUBJECT:CN=Poynt-Root, emailAddress=support@poynt.com
ISSUED:2016-01-19 00:00:00
EXPIRES:2050-01-19 00:00:00
SIGNATURE: RSA with SHA-256
RSA key size :2048
# Error Conditions
If the device is not capable of remote key loading, return error.
- PoyntError.TRUSTED_CERTS_NOT_FOUND
If no trusted certificates are found, return error
- PoyntError.TRUSTED_CERTS_NOT_FOUND
If only a bundled root CA certificate is found, return summary with the root certificate information.
# getDeviceSigningCertificateSummary()
This method returns an ASCII string representing the summary of the device signing certificate.
# Input Params
Callback - where the device signing certificate summary is returned or an error if device trusted certificates are not found.
onSuccess(String summary)
onError(PoyntError error)
# Output Params
Returns an ASCII String with Device Signing Certificate summary as part of the onSuccess() callback. The subject of the certificate must match the device serial number.
Eg.
ISSUER:CN=Manufacturer 1 RKL SubCA, emailAddress=support@poynt.com
SUBJECT:CN=PJKL123456789
ISSUED:2019-01-23 00:00:00
EXPIRES:2022-01-22 00:00:00
SIGNATURE: RSA with SHA-256
RSA key size :2048
# Error Conditions
If the device is not capable of remote key loading, return error.
- PoyntError.DEVICE_CERTS_NOT_FOUND
If no device signing certificate is found, return error.
- PoyntError.DEVICE_CERTS_NOT_FOUND
If a device has RSA keypair but no signed certificate, return error.
- PoyntError.DEVICE_CERTS_NOT_FOUND
# Errors
When returning onError() callback with a PoyntError, card reader must set the 'code' to one of the predefined error codes defined in PoyntError class. In addition to the code, "reason" field can be used to indicate a developer friendly error message and "data" field can be used to set any additional data that could be useful in troubleshooting.
Eg.
PoyntError poyntError = new PoyntError(PoyntError.*DEVICE_SIGNING_CERT_NOT_FOUND*);
poyntError.setData("No RSA keypair found");
poyntError.setReason("Device not object signed");
callback.onError(poyntError);
# Appendix
# Samples
Sample CSR Generated by Terminal -- save the following as device-csr.hex
::: details hex encoded CSR 308202ED308201D50201003081A7310B3009060355040613025553311330110603550408130A43616C69666F726E6961311230100603550407130950616C6F20416C746F3111300F060355040A1308506F796E7420436F311D301B060355040B1314506F796E7420536D617274205465726D696E616C313D303B0603550403133450364A4E33393348533030303537352F656D61696C416464726573733D7465726D696E616C2D61646D696E40706F796E742E636F30820122300D06092A864886F70D01010105000382010F003082010A0282010100836F4B8AC1F257FA3C1F8FA585EF8FA12AB7F2BD0D5486C70ACD4156A7925679B7C285F008A0FB7302A707B7EA2ECCD943181D60243DA0454CCA7C184EF747CE5344FCACB103983C149496C5EA2946C4DD57B342406C9DEAFAB1600CB4E70697A5C0F168F2A11A0F0F4E2E33469B1B770B46062EFA1EA130545F4DD40EE79FA53F7B58F2CF10694DE3F2C25EBF6AA25CC00FBE5A5642C0C2696059A52713384DDFDD06D58A5EFFFCFCCA32A8C85C21E4610AB73328878AA75F244A84133807E66067997A2DC092A69CAC993F8A1EE319FEA4C7D847F996EC9B45976E46662503C048FB3723C7CD44DAD183CB95AAA1C79DD9C92250A0ECA94F80064CB924373B0203010001A000300D06092A864886F70D01010B0500038201010021A0833045678DACB9E1C56F61C3DE01EB5018EB5F3DD04736F72F620F614466C2CEDA1348D6733DBF07B95EEED57BFE8DB2A360E5A28A51367DAA1722CCDC98873F37939150B2A75DD3FA6683577954198D2658867C60344F308910A81CB2B1B08F423B7F9885EEC149E46AA31B7F91985E065AC71831F0C778ADB3B654DBEEEBCEE57820485C6F58F9AAB1DB55878EB2CDD1B19702CACB60AEACDA0BE8692EFEC8AC046DE7152E78F57C0569D5ADB48223A59A654662942E739AB84681CA2170F56CD3EC3D95462DDE33605763E04B87024F4F3446B7AEA1F018C2DF31D8FF020C04DDE4A27449B64B775CF02DEEF320F6C468C48E8EB6E8FFC34E7394CD21 :::
Convert to DER encoding:
$xxd -r -p device-csr.hex > device-csr.der
Verify the CSR:
$openssl req -in device-csr.der -inform DER -noout -text
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=US, ST=California, L=Palo Alto, O=Poynt Co, OU=Poynt Smart Terminal, CN=P6JN393HS000575/emailAddress=terminal-admin@poynt.co
Subject Public Key Info:
….
Signed Certificate from Poynt Cloud: save the following as signed-cert.hex
::: details hex encoded certificate
3082039A30820282A00302010202074EB0D60000723A300D06092A864886F70D01010B0500308197310B3009060355040613025553310B300906035504080C024341310E300C060355040A0C05506F796E743121301F06035504410C184D616E756661637475726572203120524B4C2053756243413121301F06035504030C184D616E756661637475726572203120524B4C2053756243413125302306092A864886F70D0109011616737570706F727440766972747563727970742E636F6D301E170D3139313132343030303030305A170D3239313132323030303030305A308182310B30090603550406130255533113301106035504080C0A43616C69666F726E69613112301006035504070C0950616C6F20416C746F3111300F060355040A0C08506F796E7420436F311D301B060355040B0C14506F796E7420536D617274205465726D696E616C3118301606035504030C0F50364A4E333933485330303035373530820122300D06092A864886F70D01010105000382010F003082010A0282010100836F4B8AC1F257FA3C1F8FA585EF8FA12AB7F2BD0D5486C70ACD4156A7925679B7C285F008A0FB7302A707B7EA2ECCD943181D60243DA0454CCA7C184EF747CE5344FCACB103983C149496C5EA2946C4DD57B342406C9DEAFAB1600CB4E70697A5C0F168F2A11A0F0F4E2E33469B1B770B46062EFA1EA130545F4DD40EE79FA53F7B58F2CF10694DE3F2C25EBF6AA25CC00FBE5A5642C0C2696059A52713384DDFDD06D58A5EFFFCFCCA32A8C85C21E4610AB73328878AA75F244A84133807E66067997A2DC092A69CAC993F8A1EE319FEA4C7D847F996EC9B45976E46662503C048FB3723C7CD44DAD183CB95AAA1C79DD9C92250A0ECA94F80064CB924373B0203010001300D06092A864886F70D01010B050003820101004D37AE4378B9B512068B8685B7F38BE03E21F988D79F4EAD7C56B23B4AE71D8DFCFB30EEE55AAEC1CEAF218070981B04A023EBA267F5BB2136EFE30F1FA6D3BA33875E95E3E67DD3F4D28EC8DE7C082A8B9792DF6A3964D7F7D55A42A66073690A6033345753DA42E00355DED10900817E5B5821C066BEDBF467E3484739DC91CF86806BCF8196C3CF9B4811EF3F65255A51A3F95379C0C3CC85462DCBEC30C04DCA3832CA536C2C6A65A35522FA576E25F511DBB309DAF2C1DC19375B0897247C6ADA737546FD873E29BA293F19EE08548B0A0CF806BF9FFCFD12EF54E1C16A8B7495C20DABCEE548C7CD799D6A10FD1E316636D8F4213759F622B1F24C10A3
:::
Verify the Signed certificate:
$ openssl x509 -text -in signed-cert.der -inform DER
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 22149481352950330 (0x4eb0d60000723a)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=CA, O=Poynt/pseudonym=Manufacturer 1 RKL SubCA, CN=Manufacturer 1 RKL SubCA/emailAddress=support@virtucrypt.com
Validity
Not Before: Nov 24 00:00:00 2019 GMT
Not After : Nov 22 00:00:00 2029 GMT
Subject: C=US, ST=California, L=Palo Alto, O=Poynt Co, OU=Poynt Smart Terminal, CN=P6JN393HS000575
Subject Public Key Info:
….