# 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.

Object Signing process

  1. 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
    1. The subject of the CSR must be the serial number of the terminal.
  2. RKMS server generates Device Signing Certificate (DSC) from CSR and sends it to device
  3. DSC is saved on device's external flash.
  4. 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

  1. If a terminal is already object signed, return error

    a. PoyntError.DEVICE_ALREADY_OBJECT_SIGNED

  2. If RSA key pair generation failed, return error.

    a. PoyntError.DEVICE_RSA_KEYPAIR_GENERATION_FAILED

  3. If the serial number provided doesn't match the serial number of the card reader, return error.

    a. PoyntError.DEVICE_INVALID_SERIAL

  4. 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

  1. If a certificate is already loaded, return error.

    a. PoyntError.DEVICE_ALREADY_OBJECT_SIGNED

  2. If the keypair corresponding to the certificate being loaded is not found, return error.

    a. PoyntError.DEVICE_SIGNING_KEYPAIR_NOT_FOUND

  3. If the certificate is invalid or in incorrect format, return error

    a. PoyntError.DEVICE_INVALID_SIGNING_CERT

  4. 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

  1. If the certificate is already loaded (same signature, serial, hash), return success. If not overwrite.

  2. If the certificate is invalid or in incorrect format, return error.

    a. PoyntError.DEVICE_INVALID_TRUSTED_CERT

  3. 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:
….
Last Updated: 11/2/2020, 3:05:26 PM