client: fix mix of spaces & tabs

This commit is contained in:
Philippe Teuwen 2019-03-09 23:35:06 +01:00
commit 0d9223a547
197 changed files with 49383 additions and 49383 deletions

View file

@ -11,307 +11,307 @@
#include "apduinfo.h"
const APDUCode APDUCodeTable[] = {
// ID Type Description
{"XXXX", APDUCODE_TYPE_NONE, ""}, // blank string
{"6---", APDUCODE_TYPE_ERROR, "Class not supported."},
{"61--", APDUCODE_TYPE_INFO, "Response bytes still available"},
{"61XX", APDUCODE_TYPE_INFO, "Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE."},
{"62--", APDUCODE_TYPE_WARNING, "State of non-volatile memory unchanged"},
{"6200", APDUCODE_TYPE_WARNING, "No information given (NV-Ram not changed)"},
{"6201", APDUCODE_TYPE_WARNING, "NV-Ram not changed 1."},
{"6281", APDUCODE_TYPE_WARNING, "Part of returned data may be corrupted"},
{"6282", APDUCODE_TYPE_WARNING, "End of file/record reached before reading Le bytes"},
{"6283", APDUCODE_TYPE_WARNING, "Selected file invalidated"},
{"6284", APDUCODE_TYPE_WARNING, "Selected file is not valid. FCI not formated according to ISO"},
{"6285", APDUCODE_TYPE_WARNING, "No input data available from a sensor on the card. No Purse Engine enslaved for R3bc"},
{"62A2", APDUCODE_TYPE_WARNING, "Wrong R-MAC"},
{"62A4", APDUCODE_TYPE_WARNING, "Card locked (during reset( ))"},
{"62CX", APDUCODE_TYPE_WARNING, "Counter with value x (command dependent)"},
{"62F1", APDUCODE_TYPE_WARNING, "Wrong C-MAC"},
{"62F3", APDUCODE_TYPE_WARNING, "Internal reset"},
{"62F5", APDUCODE_TYPE_WARNING, "Default agent locked"},
{"62F7", APDUCODE_TYPE_WARNING, "Cardholder locked"},
{"62F8", APDUCODE_TYPE_WARNING, "Basement is current agent"},
{"62F9", APDUCODE_TYPE_WARNING, "CALC Key Set not unblocked"},
{"62FX", APDUCODE_TYPE_WARNING, "-"},
{"62XX", APDUCODE_TYPE_WARNING, "RFU"},
{"63--", APDUCODE_TYPE_WARNING, "State of non-volatile memory changed"},
{"6300", APDUCODE_TYPE_WARNING, "No information given (NV-Ram changed)"},
{"6381", APDUCODE_TYPE_WARNING, "File filled up by the last write. Loading/updating is not allowed."},
{"6382", APDUCODE_TYPE_WARNING, "Card key not supported."},
{"6383", APDUCODE_TYPE_WARNING, "Reader key not supported."},
{"6384", APDUCODE_TYPE_WARNING, "Plaintext transmission not supported."},
{"6385", APDUCODE_TYPE_WARNING, "Secured transmission not supported."},
{"6386", APDUCODE_TYPE_WARNING, "Volatile memory is not available."},
{"6387", APDUCODE_TYPE_WARNING, "Non-volatile memory is not available."},
{"6388", APDUCODE_TYPE_WARNING, "Key number not valid."},
{"6389", APDUCODE_TYPE_WARNING, "Key length is not correct."},
{"63C0", APDUCODE_TYPE_WARNING, "Verify fail, no try left."},
{"63C1", APDUCODE_TYPE_WARNING, "Verify fail, 1 try left."},
{"63C2", APDUCODE_TYPE_WARNING, "Verify fail, 2 tries left."},
{"63C3", APDUCODE_TYPE_WARNING, "Verify fail, 3 tries left."},
{"63CX", APDUCODE_TYPE_WARNING, "The counter has reached the value 'x' (0 = x = 15) (command dependent)."},
{"63F1", APDUCODE_TYPE_WARNING, "More data expected."},
{"63F2", APDUCODE_TYPE_WARNING, "More data expected and proactive command pending."},
{"63FX", APDUCODE_TYPE_WARNING, "-"},
{"63XX", APDUCODE_TYPE_WARNING, "RFU"},
{"64--", APDUCODE_TYPE_ERROR, "State of non-volatile memory unchanged"},
{"6400", APDUCODE_TYPE_ERROR, "No information given (NV-Ram not changed)"},
{"6401", APDUCODE_TYPE_ERROR, "Command timeout. Immediate response required by the card."},
{"64XX", APDUCODE_TYPE_ERROR, "RFU"},
{"65--", APDUCODE_TYPE_ERROR, "State of non-volatile memory changed"},
{"6500", APDUCODE_TYPE_ERROR, "No information given"},
{"6501", APDUCODE_TYPE_ERROR, "Write error. Memory failure. There have been problems in writing or reading the EEPROM. Other hardware problems may also bring this error."},
{"6581", APDUCODE_TYPE_ERROR, "Memory failure"},
{"65FX", APDUCODE_TYPE_ERROR, "-"},
{"65XX", APDUCODE_TYPE_ERROR, "RFU"},
{"66--", APDUCODE_TYPE_SECURITY, " "},
{"6600", APDUCODE_TYPE_SECURITY, "Error while receiving (timeout)"},
{"6601", APDUCODE_TYPE_SECURITY, "Error while receiving (character parity error)"},
{"6602", APDUCODE_TYPE_SECURITY, "Wrong checksum"},
{"6603", APDUCODE_TYPE_SECURITY, "The current DF file without FCI"},
{"6604", APDUCODE_TYPE_SECURITY, "No SF or KF under the current DF"},
{"6669", APDUCODE_TYPE_SECURITY, "Incorrect Encryption/Decryption Padding"},
{"66XX", APDUCODE_TYPE_SECURITY, "-"},
{"67--", APDUCODE_TYPE_ERROR, " "},
{"6700", APDUCODE_TYPE_ERROR, "Wrong length"},
{"67XX", APDUCODE_TYPE_ERROR, "length incorrect (procedure)(ISO 7816-3)"},
{"68--", APDUCODE_TYPE_ERROR, "Functions in CLA not supported"},
{"6800", APDUCODE_TYPE_ERROR, "No information given (The request function is not supported by the card)"},
{"6881", APDUCODE_TYPE_ERROR, "Logical channel not supported"},
{"6882", APDUCODE_TYPE_ERROR, "Secure messaging not supported"},
{"6883", APDUCODE_TYPE_ERROR, "Last command of the chain expected"},
{"6884", APDUCODE_TYPE_ERROR, "Command chaining not supported"},
{"68FX", APDUCODE_TYPE_ERROR, "-"},
{"68XX", APDUCODE_TYPE_ERROR, "RFU"},
{"69--", APDUCODE_TYPE_ERROR, "Command not allowed"},
{"6900", APDUCODE_TYPE_ERROR, "No information given (Command not allowed)"},
{"6901", APDUCODE_TYPE_ERROR, "Command not accepted (inactive state)"},
{"6981", APDUCODE_TYPE_ERROR, "Command incompatible with file structure"},
{"6982", APDUCODE_TYPE_ERROR, "Security condition not satisfied."},
{"6983", APDUCODE_TYPE_ERROR, "Authentication method blocked"},
{"6984", APDUCODE_TYPE_ERROR, "Referenced data reversibly blocked (invalidated)"},
{"6985", APDUCODE_TYPE_ERROR, "Conditions of use not satisfied."},
{"6986", APDUCODE_TYPE_ERROR, "Command not allowed (no current EF)"},
{"6987", APDUCODE_TYPE_ERROR, "Expected secure messaging (SM) object missing"},
{"6988", APDUCODE_TYPE_ERROR, "Incorrect secure messaging (SM) data object"},
{"698D", APDUCODE_TYPE_NONE, "Reserved"},
{"6996", APDUCODE_TYPE_ERROR, "Data must be updated again"},
{"69E1", APDUCODE_TYPE_ERROR, "POL1 of the currently Enabled Profile prevents this action."},
{"69F0", APDUCODE_TYPE_ERROR, "Permission Denied"},
{"69F1", APDUCODE_TYPE_ERROR, "Permission Denied - Missing Privilege"},
{"69FX", APDUCODE_TYPE_ERROR, "-"},
{"69XX", APDUCODE_TYPE_ERROR, "RFU"},
{"6A--", APDUCODE_TYPE_ERROR, "Wrong parameter(s) P1-P2"},
{"6A00", APDUCODE_TYPE_ERROR, "No information given (Bytes P1 and/or P2 are incorrect)"},
{"6A80", APDUCODE_TYPE_ERROR, "The parameters in the data field are incorrect."},
{"6A81", APDUCODE_TYPE_ERROR, "Function not supported"},
{"6A82", APDUCODE_TYPE_ERROR, "File not found"},
{"6A83", APDUCODE_TYPE_ERROR, "Record not found"},
{"6A84", APDUCODE_TYPE_ERROR, "There is insufficient memory space in record or file"},
{"6A85", APDUCODE_TYPE_ERROR, "Lc inconsistent with TLV structure"},
{"6A86", APDUCODE_TYPE_ERROR, "Incorrect P1 or P2 parameter."},
{"6A87", APDUCODE_TYPE_ERROR, "Lc inconsistent with P1-P2"},
{"6A88", APDUCODE_TYPE_ERROR, "Referenced data not found"},
{"6A89", APDUCODE_TYPE_ERROR, "File already exists"},
{"6A8A", APDUCODE_TYPE_ERROR, "DF name already exists."},
{"6AF0", APDUCODE_TYPE_ERROR, "Wrong parameter value"},
{"6AFX", APDUCODE_TYPE_ERROR, "-"},
{"6AXX", APDUCODE_TYPE_ERROR, "RFU"},
{"6B--", APDUCODE_TYPE_ERROR, " "},
{"6B00", APDUCODE_TYPE_ERROR, "Wrong parameter(s) P1-P2"},
{"6BXX", APDUCODE_TYPE_ERROR, "Reference incorrect (procedure byte), (ISO 7816-3)"},
{"6C--", APDUCODE_TYPE_ERROR, "Wrong length Le"},
{"6C00", APDUCODE_TYPE_ERROR, "Incorrect P3 length."},
{"6CXX", APDUCODE_TYPE_ERROR, "Bad length value in Le; 'xx' is the correct exact Le"},
{"6D--", APDUCODE_TYPE_ERROR, " "},
{"6D00", APDUCODE_TYPE_ERROR, "Instruction code not supported or invalid"},
{"6DXX", APDUCODE_TYPE_ERROR, "Instruction code not programmed or invalid (procedure byte), (ISO 7816-3)"},
{"6E--", APDUCODE_TYPE_ERROR, " "},
{"6E00", APDUCODE_TYPE_ERROR, "Class not supported"},
{"6EXX", APDUCODE_TYPE_ERROR, "Instruction class not supported (procedure byte), (ISO 7816-3)"},
{"6F--", APDUCODE_TYPE_ERROR, "Internal exception"},
{"6F00", APDUCODE_TYPE_ERROR, "Command aborted - more exact diagnosis not possible (e.g., operating system error)."},
{"6FFF", APDUCODE_TYPE_ERROR, "Card dead (overuse)"},
{"6FXX", APDUCODE_TYPE_ERROR, "No precise diagnosis (procedure byte), (ISO 7816-3)"},
{"9---", APDUCODE_TYPE_NONE, ""},
{"9000", APDUCODE_TYPE_INFO, "Command successfully executed (OK)."},
{"9004", APDUCODE_TYPE_WARNING, "PIN not succesfully verified, 3 or more PIN tries left"},
{"9008", APDUCODE_TYPE_NONE, "Key/file not found"},
{"9080", APDUCODE_TYPE_WARNING, "Unblock Try Counter has reached zero"},
{"9100", APDUCODE_TYPE_NONE, "OK"},
{"9101", APDUCODE_TYPE_NONE, "States.activity, States.lock Status or States.lockable has wrong value"},
{"9102", APDUCODE_TYPE_NONE, "Transaction number reached its limit"},
{"910C", APDUCODE_TYPE_NONE, "No changes"},
{"910E", APDUCODE_TYPE_NONE, "Insufficient NV-Memory to complete command"},
{"911C", APDUCODE_TYPE_NONE, "Command code not supported"},
{"911E", APDUCODE_TYPE_NONE, "CRC or MAC does not match data"},
{"9140", APDUCODE_TYPE_NONE, "Invalid key number specified"},
{"917E", APDUCODE_TYPE_NONE, "Length of command string invalid"},
{"919D", APDUCODE_TYPE_NONE, "Not allow the requested command"},
{"919E", APDUCODE_TYPE_NONE, "Value of the parameter invalid"},
{"91A0", APDUCODE_TYPE_NONE, "Requested AID not present on PICC"},
{"91A1", APDUCODE_TYPE_NONE, "Unrecoverable error within application"},
{"91AE", APDUCODE_TYPE_NONE, "Authentication status does not allow the requested command"},
{"91AF", APDUCODE_TYPE_NONE, "Additional data frame is expected to be sent"},
{"91BE", APDUCODE_TYPE_NONE, "Out of boundary"},
{"91C1", APDUCODE_TYPE_NONE, "Unrecoverable error within PICC"},
{"91CA", APDUCODE_TYPE_NONE, "Previous Command was not fully completed"},
{"91CD", APDUCODE_TYPE_NONE, "PICC was disabled by an unrecoverable error"},
{"91CE", APDUCODE_TYPE_NONE, "Number of Applications limited to 28"},
{"91DE", APDUCODE_TYPE_NONE, "File or application already exists"},
{"91EE", APDUCODE_TYPE_NONE, "Could not complete NV-write operation due to loss of power"},
{"91F0", APDUCODE_TYPE_NONE, "Specified file number does not exist"},
{"91F1", APDUCODE_TYPE_NONE, "Unrecoverable error within file"},
{"920x", APDUCODE_TYPE_INFO, "Writing to EEPROM successful after 'x' attempts."},
{"9210", APDUCODE_TYPE_ERROR, "Insufficient memory. No more storage available."},
{"9240", APDUCODE_TYPE_ERROR, "Writing to EEPROM not successful."},
{"9301", APDUCODE_TYPE_NONE, "Integrity error"},
{"9302", APDUCODE_TYPE_NONE, "Candidate S2 invalid"},
{"9303", APDUCODE_TYPE_ERROR, "Application is permanently locked"},
{"9400", APDUCODE_TYPE_ERROR, "No EF selected."},
{"9401", APDUCODE_TYPE_NONE, "Candidate currency code does not match purse currency"},
{"9402", APDUCODE_TYPE_NONE, "Candidate amount too high"},
{"9402", APDUCODE_TYPE_ERROR, "Address range exceeded."},
{"9403", APDUCODE_TYPE_NONE, "Candidate amount too low"},
{"9404", APDUCODE_TYPE_ERROR, "FID not found, record not found or comparison pattern not found."},
{"9405", APDUCODE_TYPE_NONE, "Problems in the data field"},
{"9406", APDUCODE_TYPE_ERROR, "Required MAC unavailable"},
{"9407", APDUCODE_TYPE_NONE, "Bad currency : purse engine has no slot with R3bc currency"},
{"9408", APDUCODE_TYPE_NONE, "R3bc currency not supported in purse engine"},
{"9408", APDUCODE_TYPE_ERROR, "Selected file type does not match command."},
{"9580", APDUCODE_TYPE_NONE, "Bad sequence"},
{"9681", APDUCODE_TYPE_NONE, "Slave not found"},
{"9700", APDUCODE_TYPE_NONE, "PIN blocked and Unblock Try Counter is 1 or 2"},
{"9702", APDUCODE_TYPE_NONE, "Main keys are blocked"},
{"9704", APDUCODE_TYPE_NONE, "PIN not succesfully verified, 3 or more PIN tries left"},
{"9784", APDUCODE_TYPE_NONE, "Base key"},
{"9785", APDUCODE_TYPE_NONE, "Limit exceeded - C-MAC key"},
{"9786", APDUCODE_TYPE_NONE, "SM error - Limit exceeded - R-MAC key"},
{"9787", APDUCODE_TYPE_NONE, "Limit exceeded - sequence counter"},
{"9788", APDUCODE_TYPE_NONE, "Limit exceeded - R-MAC length"},
{"9789", APDUCODE_TYPE_NONE, "Service not available"},
{"9802", APDUCODE_TYPE_ERROR, "No PIN defined."},
{"9804", APDUCODE_TYPE_ERROR, "Access conditions not satisfied, authentication failed."},
{"9835", APDUCODE_TYPE_ERROR, "ASK RANDOM or GIVE RANDOM not executed."},
{"9840", APDUCODE_TYPE_ERROR, "PIN verification not successful."},
{"9850", APDUCODE_TYPE_ERROR, "INCREASE or DECREASE could not be executed because a limit has been reached."},
{"9862", APDUCODE_TYPE_ERROR, "Authentication Error, application specific (incorrect MAC)"},
{"9900", APDUCODE_TYPE_NONE, "1 PIN try left"},
{"9904", APDUCODE_TYPE_NONE, "PIN not succesfully verified, 1 PIN try left"},
{"9985", APDUCODE_TYPE_NONE, "Wrong status - Cardholder lock"},
{"9986", APDUCODE_TYPE_ERROR, "Missing privilege"},
{"9987", APDUCODE_TYPE_NONE, "PIN is not installed"},
{"9988", APDUCODE_TYPE_NONE, "Wrong status - R-MAC state"},
{"9A00", APDUCODE_TYPE_NONE, "2 PIN try left"},
{"9A04", APDUCODE_TYPE_NONE, "PIN not succesfully verified, 2 PIN try left"},
{"9A71", APDUCODE_TYPE_NONE, "Wrong parameter value - Double agent AID"},
{"9A72", APDUCODE_TYPE_NONE, "Wrong parameter value - Double agent Type"},
{"9D05", APDUCODE_TYPE_ERROR, "Incorrect certificate type"},
{"9D07", APDUCODE_TYPE_ERROR, "Incorrect session data size"},
{"9D08", APDUCODE_TYPE_ERROR, "Incorrect DIR file record size"},
{"9D09", APDUCODE_TYPE_ERROR, "Incorrect FCI record size"},
{"9D0A", APDUCODE_TYPE_ERROR, "Incorrect code size"},
{"9D10", APDUCODE_TYPE_ERROR, "Insufficient memory to load application"},
{"9D11", APDUCODE_TYPE_ERROR, "Invalid AID"},
{"9D12", APDUCODE_TYPE_ERROR, "Duplicate AID"},
{"9D13", APDUCODE_TYPE_ERROR, "Application previously loaded"},
{"9D14", APDUCODE_TYPE_ERROR, "Application history list full"},
{"9D15", APDUCODE_TYPE_ERROR, "Application not open"},
{"9D17", APDUCODE_TYPE_ERROR, "Invalid offset"},
{"9D18", APDUCODE_TYPE_ERROR, "Application already loaded"},
{"9D19", APDUCODE_TYPE_ERROR, "Invalid certificate"},
{"9D1A", APDUCODE_TYPE_ERROR, "Invalid signature"},
{"9D1B", APDUCODE_TYPE_ERROR, "Invalid KTU"},
{"9D1D", APDUCODE_TYPE_ERROR, "MSM controls not set"},
{"9D1E", APDUCODE_TYPE_ERROR, "Application signature does not exist"},
{"9D1F", APDUCODE_TYPE_ERROR, "KTU does not exist"},
{"9D20", APDUCODE_TYPE_ERROR, "Application not loaded"},
{"9D21", APDUCODE_TYPE_ERROR, "Invalid Open command data length"},
{"9D30", APDUCODE_TYPE_ERROR, "Check data parameter is incorrect (invalid start address)"},
{"9D31", APDUCODE_TYPE_ERROR, "Check data parameter is incorrect (invalid length)"},
{"9D32", APDUCODE_TYPE_ERROR, "Check data parameter is incorrect (illegal memory check area)"},
{"9D40", APDUCODE_TYPE_ERROR, "Invalid MSM Controls ciphertext"},
{"9D41", APDUCODE_TYPE_ERROR, "MSM controls already set"},
{"9D42", APDUCODE_TYPE_ERROR, "Set MSM Controls data length less than 2 bytes"},
{"9D43", APDUCODE_TYPE_ERROR, "Invalid MSM Controls data length"},
{"9D44", APDUCODE_TYPE_ERROR, "Excess MSM Controls ciphertext"},
{"9D45", APDUCODE_TYPE_ERROR, "Verification of MSM Controls data failed"},
{"9D50", APDUCODE_TYPE_ERROR, "Invalid MCD Issuer production ID"},
{"9D51", APDUCODE_TYPE_ERROR, "Invalid MCD Issuer ID"},
{"9D52", APDUCODE_TYPE_ERROR, "Invalid set MSM controls data date"},
{"9D53", APDUCODE_TYPE_ERROR, "Invalid MCD number"},
{"9D54", APDUCODE_TYPE_ERROR, "Reserved field error"},
{"9D55", APDUCODE_TYPE_ERROR, "Reserved field error"},
{"9D56", APDUCODE_TYPE_ERROR, "Reserved field error"},
{"9D57", APDUCODE_TYPE_ERROR, "Reserved field error"},
{"9D60", APDUCODE_TYPE_ERROR, "MAC verification failed"},
{"9D61", APDUCODE_TYPE_ERROR, "Maximum number of unblocks reached"},
{"9D62", APDUCODE_TYPE_ERROR, "Card was not blocked"},
{"9D63", APDUCODE_TYPE_ERROR, "Crypto functions not available"},
{"9D64", APDUCODE_TYPE_ERROR, "No application loaded"},
{"9E00", APDUCODE_TYPE_NONE, "PIN not installed"},
{"9E04", APDUCODE_TYPE_NONE, "PIN not succesfully verified, PIN not installed"},
{"9F00", APDUCODE_TYPE_NONE, "PIN blocked and Unblock Try Counter is 3"},
{"9F04", APDUCODE_TYPE_NONE, "PIN not succesfully verified, PIN blocked and Unblock Try Counter is 3"},
{"9FXX", APDUCODE_TYPE_NONE, "Command successfully executed; 'xx' bytes of data are available and can be requested using GET RESPONSE."},
{"9XXX", APDUCODE_TYPE_NONE, "Application related status, (ISO 7816-3)"}
// ID Type Description
{"XXXX", APDUCODE_TYPE_NONE, ""}, // blank string
{"6---", APDUCODE_TYPE_ERROR, "Class not supported."},
{"61--", APDUCODE_TYPE_INFO, "Response bytes still available"},
{"61XX", APDUCODE_TYPE_INFO, "Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE."},
{"62--", APDUCODE_TYPE_WARNING, "State of non-volatile memory unchanged"},
{"6200", APDUCODE_TYPE_WARNING, "No information given (NV-Ram not changed)"},
{"6201", APDUCODE_TYPE_WARNING, "NV-Ram not changed 1."},
{"6281", APDUCODE_TYPE_WARNING, "Part of returned data may be corrupted"},
{"6282", APDUCODE_TYPE_WARNING, "End of file/record reached before reading Le bytes"},
{"6283", APDUCODE_TYPE_WARNING, "Selected file invalidated"},
{"6284", APDUCODE_TYPE_WARNING, "Selected file is not valid. FCI not formated according to ISO"},
{"6285", APDUCODE_TYPE_WARNING, "No input data available from a sensor on the card. No Purse Engine enslaved for R3bc"},
{"62A2", APDUCODE_TYPE_WARNING, "Wrong R-MAC"},
{"62A4", APDUCODE_TYPE_WARNING, "Card locked (during reset( ))"},
{"62CX", APDUCODE_TYPE_WARNING, "Counter with value x (command dependent)"},
{"62F1", APDUCODE_TYPE_WARNING, "Wrong C-MAC"},
{"62F3", APDUCODE_TYPE_WARNING, "Internal reset"},
{"62F5", APDUCODE_TYPE_WARNING, "Default agent locked"},
{"62F7", APDUCODE_TYPE_WARNING, "Cardholder locked"},
{"62F8", APDUCODE_TYPE_WARNING, "Basement is current agent"},
{"62F9", APDUCODE_TYPE_WARNING, "CALC Key Set not unblocked"},
{"62FX", APDUCODE_TYPE_WARNING, "-"},
{"62XX", APDUCODE_TYPE_WARNING, "RFU"},
{"63--", APDUCODE_TYPE_WARNING, "State of non-volatile memory changed"},
{"6300", APDUCODE_TYPE_WARNING, "No information given (NV-Ram changed)"},
{"6381", APDUCODE_TYPE_WARNING, "File filled up by the last write. Loading/updating is not allowed."},
{"6382", APDUCODE_TYPE_WARNING, "Card key not supported."},
{"6383", APDUCODE_TYPE_WARNING, "Reader key not supported."},
{"6384", APDUCODE_TYPE_WARNING, "Plaintext transmission not supported."},
{"6385", APDUCODE_TYPE_WARNING, "Secured transmission not supported."},
{"6386", APDUCODE_TYPE_WARNING, "Volatile memory is not available."},
{"6387", APDUCODE_TYPE_WARNING, "Non-volatile memory is not available."},
{"6388", APDUCODE_TYPE_WARNING, "Key number not valid."},
{"6389", APDUCODE_TYPE_WARNING, "Key length is not correct."},
{"63C0", APDUCODE_TYPE_WARNING, "Verify fail, no try left."},
{"63C1", APDUCODE_TYPE_WARNING, "Verify fail, 1 try left."},
{"63C2", APDUCODE_TYPE_WARNING, "Verify fail, 2 tries left."},
{"63C3", APDUCODE_TYPE_WARNING, "Verify fail, 3 tries left."},
{"63CX", APDUCODE_TYPE_WARNING, "The counter has reached the value 'x' (0 = x = 15) (command dependent)."},
{"63F1", APDUCODE_TYPE_WARNING, "More data expected."},
{"63F2", APDUCODE_TYPE_WARNING, "More data expected and proactive command pending."},
{"63FX", APDUCODE_TYPE_WARNING, "-"},
{"63XX", APDUCODE_TYPE_WARNING, "RFU"},
{"64--", APDUCODE_TYPE_ERROR, "State of non-volatile memory unchanged"},
{"6400", APDUCODE_TYPE_ERROR, "No information given (NV-Ram not changed)"},
{"6401", APDUCODE_TYPE_ERROR, "Command timeout. Immediate response required by the card."},
{"64XX", APDUCODE_TYPE_ERROR, "RFU"},
{"65--", APDUCODE_TYPE_ERROR, "State of non-volatile memory changed"},
{"6500", APDUCODE_TYPE_ERROR, "No information given"},
{"6501", APDUCODE_TYPE_ERROR, "Write error. Memory failure. There have been problems in writing or reading the EEPROM. Other hardware problems may also bring this error."},
{"6581", APDUCODE_TYPE_ERROR, "Memory failure"},
{"65FX", APDUCODE_TYPE_ERROR, "-"},
{"65XX", APDUCODE_TYPE_ERROR, "RFU"},
{"66--", APDUCODE_TYPE_SECURITY, " "},
{"6600", APDUCODE_TYPE_SECURITY, "Error while receiving (timeout)"},
{"6601", APDUCODE_TYPE_SECURITY, "Error while receiving (character parity error)"},
{"6602", APDUCODE_TYPE_SECURITY, "Wrong checksum"},
{"6603", APDUCODE_TYPE_SECURITY, "The current DF file without FCI"},
{"6604", APDUCODE_TYPE_SECURITY, "No SF or KF under the current DF"},
{"6669", APDUCODE_TYPE_SECURITY, "Incorrect Encryption/Decryption Padding"},
{"66XX", APDUCODE_TYPE_SECURITY, "-"},
{"67--", APDUCODE_TYPE_ERROR, " "},
{"6700", APDUCODE_TYPE_ERROR, "Wrong length"},
{"67XX", APDUCODE_TYPE_ERROR, "length incorrect (procedure)(ISO 7816-3)"},
{"68--", APDUCODE_TYPE_ERROR, "Functions in CLA not supported"},
{"6800", APDUCODE_TYPE_ERROR, "No information given (The request function is not supported by the card)"},
{"6881", APDUCODE_TYPE_ERROR, "Logical channel not supported"},
{"6882", APDUCODE_TYPE_ERROR, "Secure messaging not supported"},
{"6883", APDUCODE_TYPE_ERROR, "Last command of the chain expected"},
{"6884", APDUCODE_TYPE_ERROR, "Command chaining not supported"},
{"68FX", APDUCODE_TYPE_ERROR, "-"},
{"68XX", APDUCODE_TYPE_ERROR, "RFU"},
{"69--", APDUCODE_TYPE_ERROR, "Command not allowed"},
{"6900", APDUCODE_TYPE_ERROR, "No information given (Command not allowed)"},
{"6901", APDUCODE_TYPE_ERROR, "Command not accepted (inactive state)"},
{"6981", APDUCODE_TYPE_ERROR, "Command incompatible with file structure"},
{"6982", APDUCODE_TYPE_ERROR, "Security condition not satisfied."},
{"6983", APDUCODE_TYPE_ERROR, "Authentication method blocked"},
{"6984", APDUCODE_TYPE_ERROR, "Referenced data reversibly blocked (invalidated)"},
{"6985", APDUCODE_TYPE_ERROR, "Conditions of use not satisfied."},
{"6986", APDUCODE_TYPE_ERROR, "Command not allowed (no current EF)"},
{"6987", APDUCODE_TYPE_ERROR, "Expected secure messaging (SM) object missing"},
{"6988", APDUCODE_TYPE_ERROR, "Incorrect secure messaging (SM) data object"},
{"698D", APDUCODE_TYPE_NONE, "Reserved"},
{"6996", APDUCODE_TYPE_ERROR, "Data must be updated again"},
{"69E1", APDUCODE_TYPE_ERROR, "POL1 of the currently Enabled Profile prevents this action."},
{"69F0", APDUCODE_TYPE_ERROR, "Permission Denied"},
{"69F1", APDUCODE_TYPE_ERROR, "Permission Denied - Missing Privilege"},
{"69FX", APDUCODE_TYPE_ERROR, "-"},
{"69XX", APDUCODE_TYPE_ERROR, "RFU"},
{"6A--", APDUCODE_TYPE_ERROR, "Wrong parameter(s) P1-P2"},
{"6A00", APDUCODE_TYPE_ERROR, "No information given (Bytes P1 and/or P2 are incorrect)"},
{"6A80", APDUCODE_TYPE_ERROR, "The parameters in the data field are incorrect."},
{"6A81", APDUCODE_TYPE_ERROR, "Function not supported"},
{"6A82", APDUCODE_TYPE_ERROR, "File not found"},
{"6A83", APDUCODE_TYPE_ERROR, "Record not found"},
{"6A84", APDUCODE_TYPE_ERROR, "There is insufficient memory space in record or file"},
{"6A85", APDUCODE_TYPE_ERROR, "Lc inconsistent with TLV structure"},
{"6A86", APDUCODE_TYPE_ERROR, "Incorrect P1 or P2 parameter."},
{"6A87", APDUCODE_TYPE_ERROR, "Lc inconsistent with P1-P2"},
{"6A88", APDUCODE_TYPE_ERROR, "Referenced data not found"},
{"6A89", APDUCODE_TYPE_ERROR, "File already exists"},
{"6A8A", APDUCODE_TYPE_ERROR, "DF name already exists."},
{"6AF0", APDUCODE_TYPE_ERROR, "Wrong parameter value"},
{"6AFX", APDUCODE_TYPE_ERROR, "-"},
{"6AXX", APDUCODE_TYPE_ERROR, "RFU"},
{"6B--", APDUCODE_TYPE_ERROR, " "},
{"6B00", APDUCODE_TYPE_ERROR, "Wrong parameter(s) P1-P2"},
{"6BXX", APDUCODE_TYPE_ERROR, "Reference incorrect (procedure byte), (ISO 7816-3)"},
{"6C--", APDUCODE_TYPE_ERROR, "Wrong length Le"},
{"6C00", APDUCODE_TYPE_ERROR, "Incorrect P3 length."},
{"6CXX", APDUCODE_TYPE_ERROR, "Bad length value in Le; 'xx' is the correct exact Le"},
{"6D--", APDUCODE_TYPE_ERROR, " "},
{"6D00", APDUCODE_TYPE_ERROR, "Instruction code not supported or invalid"},
{"6DXX", APDUCODE_TYPE_ERROR, "Instruction code not programmed or invalid (procedure byte), (ISO 7816-3)"},
{"6E--", APDUCODE_TYPE_ERROR, " "},
{"6E00", APDUCODE_TYPE_ERROR, "Class not supported"},
{"6EXX", APDUCODE_TYPE_ERROR, "Instruction class not supported (procedure byte), (ISO 7816-3)"},
{"6F--", APDUCODE_TYPE_ERROR, "Internal exception"},
{"6F00", APDUCODE_TYPE_ERROR, "Command aborted - more exact diagnosis not possible (e.g., operating system error)."},
{"6FFF", APDUCODE_TYPE_ERROR, "Card dead (overuse)"},
{"6FXX", APDUCODE_TYPE_ERROR, "No precise diagnosis (procedure byte), (ISO 7816-3)"},
{"9---", APDUCODE_TYPE_NONE, ""},
{"9000", APDUCODE_TYPE_INFO, "Command successfully executed (OK)."},
{"9004", APDUCODE_TYPE_WARNING, "PIN not succesfully verified, 3 or more PIN tries left"},
{"9008", APDUCODE_TYPE_NONE, "Key/file not found"},
{"9080", APDUCODE_TYPE_WARNING, "Unblock Try Counter has reached zero"},
{"9100", APDUCODE_TYPE_NONE, "OK"},
{"9101", APDUCODE_TYPE_NONE, "States.activity, States.lock Status or States.lockable has wrong value"},
{"9102", APDUCODE_TYPE_NONE, "Transaction number reached its limit"},
{"910C", APDUCODE_TYPE_NONE, "No changes"},
{"910E", APDUCODE_TYPE_NONE, "Insufficient NV-Memory to complete command"},
{"911C", APDUCODE_TYPE_NONE, "Command code not supported"},
{"911E", APDUCODE_TYPE_NONE, "CRC or MAC does not match data"},
{"9140", APDUCODE_TYPE_NONE, "Invalid key number specified"},
{"917E", APDUCODE_TYPE_NONE, "Length of command string invalid"},
{"919D", APDUCODE_TYPE_NONE, "Not allow the requested command"},
{"919E", APDUCODE_TYPE_NONE, "Value of the parameter invalid"},
{"91A0", APDUCODE_TYPE_NONE, "Requested AID not present on PICC"},
{"91A1", APDUCODE_TYPE_NONE, "Unrecoverable error within application"},
{"91AE", APDUCODE_TYPE_NONE, "Authentication status does not allow the requested command"},
{"91AF", APDUCODE_TYPE_NONE, "Additional data frame is expected to be sent"},
{"91BE", APDUCODE_TYPE_NONE, "Out of boundary"},
{"91C1", APDUCODE_TYPE_NONE, "Unrecoverable error within PICC"},
{"91CA", APDUCODE_TYPE_NONE, "Previous Command was not fully completed"},
{"91CD", APDUCODE_TYPE_NONE, "PICC was disabled by an unrecoverable error"},
{"91CE", APDUCODE_TYPE_NONE, "Number of Applications limited to 28"},
{"91DE", APDUCODE_TYPE_NONE, "File or application already exists"},
{"91EE", APDUCODE_TYPE_NONE, "Could not complete NV-write operation due to loss of power"},
{"91F0", APDUCODE_TYPE_NONE, "Specified file number does not exist"},
{"91F1", APDUCODE_TYPE_NONE, "Unrecoverable error within file"},
{"920x", APDUCODE_TYPE_INFO, "Writing to EEPROM successful after 'x' attempts."},
{"9210", APDUCODE_TYPE_ERROR, "Insufficient memory. No more storage available."},
{"9240", APDUCODE_TYPE_ERROR, "Writing to EEPROM not successful."},
{"9301", APDUCODE_TYPE_NONE, "Integrity error"},
{"9302", APDUCODE_TYPE_NONE, "Candidate S2 invalid"},
{"9303", APDUCODE_TYPE_ERROR, "Application is permanently locked"},
{"9400", APDUCODE_TYPE_ERROR, "No EF selected."},
{"9401", APDUCODE_TYPE_NONE, "Candidate currency code does not match purse currency"},
{"9402", APDUCODE_TYPE_NONE, "Candidate amount too high"},
{"9402", APDUCODE_TYPE_ERROR, "Address range exceeded."},
{"9403", APDUCODE_TYPE_NONE, "Candidate amount too low"},
{"9404", APDUCODE_TYPE_ERROR, "FID not found, record not found or comparison pattern not found."},
{"9405", APDUCODE_TYPE_NONE, "Problems in the data field"},
{"9406", APDUCODE_TYPE_ERROR, "Required MAC unavailable"},
{"9407", APDUCODE_TYPE_NONE, "Bad currency : purse engine has no slot with R3bc currency"},
{"9408", APDUCODE_TYPE_NONE, "R3bc currency not supported in purse engine"},
{"9408", APDUCODE_TYPE_ERROR, "Selected file type does not match command."},
{"9580", APDUCODE_TYPE_NONE, "Bad sequence"},
{"9681", APDUCODE_TYPE_NONE, "Slave not found"},
{"9700", APDUCODE_TYPE_NONE, "PIN blocked and Unblock Try Counter is 1 or 2"},
{"9702", APDUCODE_TYPE_NONE, "Main keys are blocked"},
{"9704", APDUCODE_TYPE_NONE, "PIN not succesfully verified, 3 or more PIN tries left"},
{"9784", APDUCODE_TYPE_NONE, "Base key"},
{"9785", APDUCODE_TYPE_NONE, "Limit exceeded - C-MAC key"},
{"9786", APDUCODE_TYPE_NONE, "SM error - Limit exceeded - R-MAC key"},
{"9787", APDUCODE_TYPE_NONE, "Limit exceeded - sequence counter"},
{"9788", APDUCODE_TYPE_NONE, "Limit exceeded - R-MAC length"},
{"9789", APDUCODE_TYPE_NONE, "Service not available"},
{"9802", APDUCODE_TYPE_ERROR, "No PIN defined."},
{"9804", APDUCODE_TYPE_ERROR, "Access conditions not satisfied, authentication failed."},
{"9835", APDUCODE_TYPE_ERROR, "ASK RANDOM or GIVE RANDOM not executed."},
{"9840", APDUCODE_TYPE_ERROR, "PIN verification not successful."},
{"9850", APDUCODE_TYPE_ERROR, "INCREASE or DECREASE could not be executed because a limit has been reached."},
{"9862", APDUCODE_TYPE_ERROR, "Authentication Error, application specific (incorrect MAC)"},
{"9900", APDUCODE_TYPE_NONE, "1 PIN try left"},
{"9904", APDUCODE_TYPE_NONE, "PIN not succesfully verified, 1 PIN try left"},
{"9985", APDUCODE_TYPE_NONE, "Wrong status - Cardholder lock"},
{"9986", APDUCODE_TYPE_ERROR, "Missing privilege"},
{"9987", APDUCODE_TYPE_NONE, "PIN is not installed"},
{"9988", APDUCODE_TYPE_NONE, "Wrong status - R-MAC state"},
{"9A00", APDUCODE_TYPE_NONE, "2 PIN try left"},
{"9A04", APDUCODE_TYPE_NONE, "PIN not succesfully verified, 2 PIN try left"},
{"9A71", APDUCODE_TYPE_NONE, "Wrong parameter value - Double agent AID"},
{"9A72", APDUCODE_TYPE_NONE, "Wrong parameter value - Double agent Type"},
{"9D05", APDUCODE_TYPE_ERROR, "Incorrect certificate type"},
{"9D07", APDUCODE_TYPE_ERROR, "Incorrect session data size"},
{"9D08", APDUCODE_TYPE_ERROR, "Incorrect DIR file record size"},
{"9D09", APDUCODE_TYPE_ERROR, "Incorrect FCI record size"},
{"9D0A", APDUCODE_TYPE_ERROR, "Incorrect code size"},
{"9D10", APDUCODE_TYPE_ERROR, "Insufficient memory to load application"},
{"9D11", APDUCODE_TYPE_ERROR, "Invalid AID"},
{"9D12", APDUCODE_TYPE_ERROR, "Duplicate AID"},
{"9D13", APDUCODE_TYPE_ERROR, "Application previously loaded"},
{"9D14", APDUCODE_TYPE_ERROR, "Application history list full"},
{"9D15", APDUCODE_TYPE_ERROR, "Application not open"},
{"9D17", APDUCODE_TYPE_ERROR, "Invalid offset"},
{"9D18", APDUCODE_TYPE_ERROR, "Application already loaded"},
{"9D19", APDUCODE_TYPE_ERROR, "Invalid certificate"},
{"9D1A", APDUCODE_TYPE_ERROR, "Invalid signature"},
{"9D1B", APDUCODE_TYPE_ERROR, "Invalid KTU"},
{"9D1D", APDUCODE_TYPE_ERROR, "MSM controls not set"},
{"9D1E", APDUCODE_TYPE_ERROR, "Application signature does not exist"},
{"9D1F", APDUCODE_TYPE_ERROR, "KTU does not exist"},
{"9D20", APDUCODE_TYPE_ERROR, "Application not loaded"},
{"9D21", APDUCODE_TYPE_ERROR, "Invalid Open command data length"},
{"9D30", APDUCODE_TYPE_ERROR, "Check data parameter is incorrect (invalid start address)"},
{"9D31", APDUCODE_TYPE_ERROR, "Check data parameter is incorrect (invalid length)"},
{"9D32", APDUCODE_TYPE_ERROR, "Check data parameter is incorrect (illegal memory check area)"},
{"9D40", APDUCODE_TYPE_ERROR, "Invalid MSM Controls ciphertext"},
{"9D41", APDUCODE_TYPE_ERROR, "MSM controls already set"},
{"9D42", APDUCODE_TYPE_ERROR, "Set MSM Controls data length less than 2 bytes"},
{"9D43", APDUCODE_TYPE_ERROR, "Invalid MSM Controls data length"},
{"9D44", APDUCODE_TYPE_ERROR, "Excess MSM Controls ciphertext"},
{"9D45", APDUCODE_TYPE_ERROR, "Verification of MSM Controls data failed"},
{"9D50", APDUCODE_TYPE_ERROR, "Invalid MCD Issuer production ID"},
{"9D51", APDUCODE_TYPE_ERROR, "Invalid MCD Issuer ID"},
{"9D52", APDUCODE_TYPE_ERROR, "Invalid set MSM controls data date"},
{"9D53", APDUCODE_TYPE_ERROR, "Invalid MCD number"},
{"9D54", APDUCODE_TYPE_ERROR, "Reserved field error"},
{"9D55", APDUCODE_TYPE_ERROR, "Reserved field error"},
{"9D56", APDUCODE_TYPE_ERROR, "Reserved field error"},
{"9D57", APDUCODE_TYPE_ERROR, "Reserved field error"},
{"9D60", APDUCODE_TYPE_ERROR, "MAC verification failed"},
{"9D61", APDUCODE_TYPE_ERROR, "Maximum number of unblocks reached"},
{"9D62", APDUCODE_TYPE_ERROR, "Card was not blocked"},
{"9D63", APDUCODE_TYPE_ERROR, "Crypto functions not available"},
{"9D64", APDUCODE_TYPE_ERROR, "No application loaded"},
{"9E00", APDUCODE_TYPE_NONE, "PIN not installed"},
{"9E04", APDUCODE_TYPE_NONE, "PIN not succesfully verified, PIN not installed"},
{"9F00", APDUCODE_TYPE_NONE, "PIN blocked and Unblock Try Counter is 3"},
{"9F04", APDUCODE_TYPE_NONE, "PIN not succesfully verified, PIN blocked and Unblock Try Counter is 3"},
{"9FXX", APDUCODE_TYPE_NONE, "Command successfully executed; 'xx' bytes of data are available and can be requested using GET RESPONSE."},
{"9XXX", APDUCODE_TYPE_NONE, "Application related status, (ISO 7816-3)"}
};
const size_t APDUCodeTableLen = sizeof(APDUCodeTable)/sizeof(APDUCode);
int CodeCmp(const char *code1, const char *code2) {
int xsymb = 0;
int cmp = 0;
for (int i = 0; i < 4; i++) {
if (code1[i] == code2[i])
cmp++;
if (code1[i] == 'X' || code2[i] == 'X')
xsymb++;
}
if (cmp == 4)
return 0;
int xsymb = 0;
int cmp = 0;
for (int i = 0; i < 4; i++) {
if (code1[i] == code2[i])
cmp++;
if (code1[i] == 'X' || code2[i] == 'X')
xsymb++;
}
if (cmp == 4)
return 0;
if (cmp + xsymb == 4)
return xsymb;
if (cmp + xsymb == 4)
return xsymb;
return -1;
return -1;
}
const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) {
char buf[6] = {0};
int res;
int mineq = APDUCodeTableLen;
int mineqindx = 0;
char buf[6] = {0};
int res;
int mineq = APDUCodeTableLen;
int mineqindx = 0;
sprintf(buf, "%02X%02X", sw1, sw2);
sprintf(buf, "%02X%02X", sw1, sw2);
for (int i = 0; i < APDUCodeTableLen; i++) {
res = CodeCmp(APDUCodeTable[i].ID, buf);
for (int i = 0; i < APDUCodeTableLen; i++) {
res = CodeCmp(APDUCodeTable[i].ID, buf);
// equal
if (res == 0) {
return &APDUCodeTable[i];
}
// equal
if (res == 0) {
return &APDUCodeTable[i];
}
// with some 'X'
if (res > 0 && mineq > res) {
mineq = res;
mineqindx = i;
}
}
// with some 'X'
if (res > 0 && mineq > res) {
mineq = res;
mineqindx = i;
}
}
// if we have not equal, but with some 'X'
if (mineqindx < APDUCodeTableLen) {
return &APDUCodeTable[mineqindx];
}
// if we have not equal, but with some 'X'
if (mineqindx < APDUCodeTableLen) {
return &APDUCodeTable[mineqindx];
}
return NULL;
return NULL;
}
const char* GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2) {
const APDUCode *cd = GetAPDUCode(sw1, sw2);
if (cd)
return cd->Description;
else
return APDUCodeTable[0].Description; //empty string
const APDUCode *cd = GetAPDUCode(sw1, sw2);
if (cd)
return cd->Description;
else
return APDUCodeTable[0].Description; //empty string
}

View file

@ -16,16 +16,16 @@
#include <stdlib.h>
#include <inttypes.h>
#define APDUCODE_TYPE_NONE 0
#define APDUCODE_TYPE_INFO 1
#define APDUCODE_TYPE_WARNING 2
#define APDUCODE_TYPE_ERROR 3
#define APDUCODE_TYPE_SECURITY 4
#define APDUCODE_TYPE_NONE 0
#define APDUCODE_TYPE_INFO 1
#define APDUCODE_TYPE_WARNING 2
#define APDUCODE_TYPE_ERROR 3
#define APDUCODE_TYPE_SECURITY 4
typedef struct {
const char *ID;
const uint8_t Type;
const char *Description;
const char *ID;
const uint8_t Type;
const char *Description;
} APDUCode;
extern const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2);

File diff suppressed because it is too large Load diff

View file

@ -26,154 +26,154 @@ static struct crypto_backend *crypto_backend;
static bool crypto_init(void)
{
if (crypto_backend)
return true;
if (crypto_backend)
return true;
crypto_backend = crypto_polarssl_init();
crypto_backend = crypto_polarssl_init();
if (!crypto_backend)
return false;
if (!crypto_backend)
return false;
return true;
return true;
}
struct crypto_hash *crypto_hash_open(enum crypto_algo_hash hash)
{
struct crypto_hash *ch;
struct crypto_hash *ch;
if (!crypto_init())
return NULL;
if (!crypto_init())
return NULL;
ch = crypto_backend->hash_open(hash);
if (ch)
ch->algo = hash;
ch = crypto_backend->hash_open(hash);
if (ch)
ch->algo = hash;
return ch;
return ch;
}
void crypto_hash_close(struct crypto_hash *ch)
{
ch->close(ch);
ch->close(ch);
}
void crypto_hash_write(struct crypto_hash *ch, const unsigned char *buf, size_t len)
{
ch->write(ch, buf, len);
ch->write(ch, buf, len);
}
unsigned char *crypto_hash_read(struct crypto_hash *ch)
{
return ch->read(ch);
return ch->read(ch);
}
size_t crypto_hash_get_size(const struct crypto_hash *ch)
{
return ch->get_size(ch);
return ch->get_size(ch);
}
struct crypto_pk *crypto_pk_open(enum crypto_algo_pk pk, ...)
{
struct crypto_pk *cp;
va_list vl;
struct crypto_pk *cp;
va_list vl;
if (!crypto_init())
return NULL;
if (!crypto_init())
return NULL;
va_start(vl, pk);
cp = crypto_backend->pk_open(pk, vl);
va_end(vl);
va_start(vl, pk);
cp = crypto_backend->pk_open(pk, vl);
va_end(vl);
if (cp)
cp->algo = pk;
if (cp)
cp->algo = pk;
return cp;
return cp;
}
struct crypto_pk *crypto_pk_open_priv(enum crypto_algo_pk pk, ...)
{
struct crypto_pk *cp;
va_list vl;
struct crypto_pk *cp;
va_list vl;
if (!crypto_init())
return NULL;
if (!crypto_init())
return NULL;
if (!crypto_backend->pk_open_priv)
return NULL;
if (!crypto_backend->pk_open_priv)
return NULL;
va_start(vl, pk);
cp = crypto_backend->pk_open_priv(pk, vl);
va_end(vl);
va_start(vl, pk);
cp = crypto_backend->pk_open_priv(pk, vl);
va_end(vl);
if (cp)
cp->algo = pk;
if (cp)
cp->algo = pk;
return cp;
return cp;
}
struct crypto_pk *crypto_pk_genkey(enum crypto_algo_pk pk, ...)
{
struct crypto_pk *cp;
va_list vl;
struct crypto_pk *cp;
va_list vl;
if (!crypto_init())
return NULL;
if (!crypto_init())
return NULL;
if (!crypto_backend->pk_genkey)
return NULL;
if (!crypto_backend->pk_genkey)
return NULL;
va_start(vl, pk);
cp = crypto_backend->pk_genkey(pk, vl);
va_end(vl);
va_start(vl, pk);
cp = crypto_backend->pk_genkey(pk, vl);
va_end(vl);
if (cp)
cp->algo = pk;
if (cp)
cp->algo = pk;
return cp;
return cp;
}
void crypto_pk_close(struct crypto_pk *cp)
{
cp->close(cp);
cp->close(cp);
}
unsigned char *crypto_pk_encrypt(const struct crypto_pk *cp, const unsigned char *buf, size_t len, size_t *clen)
{
return cp->encrypt(cp, buf, len, clen);
return cp->encrypt(cp, buf, len, clen);
}
unsigned char *crypto_pk_decrypt(const struct crypto_pk *cp, const unsigned char *buf, size_t len, size_t *clen)
{
if (!cp->decrypt) {
*clen = 0;
if (!cp->decrypt) {
*clen = 0;
return NULL;
}
return NULL;
}
return cp->decrypt(cp, buf, len, clen);
return cp->decrypt(cp, buf, len, clen);
}
enum crypto_algo_pk crypto_pk_get_algo(const struct crypto_pk *cp)
{
if (!cp)
return PK_INVALID;
if (!cp)
return PK_INVALID;
return cp->algo;
return cp->algo;
}
size_t crypto_pk_get_nbits(const struct crypto_pk *cp)
{
if (!cp->get_nbits)
return 0;
if (!cp->get_nbits)
return 0;
return cp->get_nbits(cp);
return cp->get_nbits(cp);
}
unsigned char *crypto_pk_get_parameter(const struct crypto_pk *cp, unsigned param, size_t *plen)
{
*plen = 0;
*plen = 0;
if (!cp->get_parameter)
return NULL;
if (!cp->get_parameter)
return NULL;
return cp->get_parameter(cp, param, plen);
return cp->get_parameter(cp, param, plen);
}

View file

@ -20,8 +20,8 @@
#include <stddef.h>
enum crypto_algo_hash {
HASH_INVALID,
HASH_SHA_1,
HASH_INVALID,
HASH_SHA_1,
};
struct crypto_hash *crypto_hash_open(enum crypto_algo_hash hash);
@ -31,8 +31,8 @@ unsigned char *crypto_hash_read(struct crypto_hash *ch);
size_t crypto_hash_get_size(const struct crypto_hash *ch);
enum crypto_algo_pk {
PK_INVALID,
PK_RSA,
PK_INVALID,
PK_RSA,
};
struct crypto_pk *crypto_pk_open(enum crypto_algo_pk pk, ...);

View file

@ -22,27 +22,27 @@
#include <stdarg.h>
struct crypto_hash {
enum crypto_algo_hash algo;
void (*write)(struct crypto_hash *ch, const unsigned char *buf, size_t len);
unsigned char *(*read)(struct crypto_hash *ch);
void (*close)(struct crypto_hash *ch);
size_t (*get_size)(const struct crypto_hash *ch);
enum crypto_algo_hash algo;
void (*write)(struct crypto_hash *ch, const unsigned char *buf, size_t len);
unsigned char *(*read)(struct crypto_hash *ch);
void (*close)(struct crypto_hash *ch);
size_t (*get_size)(const struct crypto_hash *ch);
};
struct crypto_pk {
enum crypto_algo_pk algo;
unsigned char *(*encrypt)(const struct crypto_pk *cp, const unsigned char *buf, size_t len, size_t *clen);
unsigned char *(*decrypt)(const struct crypto_pk *cp, const unsigned char *buf, size_t len, size_t *clen);
unsigned char *(*get_parameter)(const struct crypto_pk *cp, unsigned param, size_t *plen);
size_t (*get_nbits)(const struct crypto_pk *cp);
void (*close)(struct crypto_pk *cp);
enum crypto_algo_pk algo;
unsigned char *(*encrypt)(const struct crypto_pk *cp, const unsigned char *buf, size_t len, size_t *clen);
unsigned char *(*decrypt)(const struct crypto_pk *cp, const unsigned char *buf, size_t len, size_t *clen);
unsigned char *(*get_parameter)(const struct crypto_pk *cp, unsigned param, size_t *plen);
size_t (*get_nbits)(const struct crypto_pk *cp);
void (*close)(struct crypto_pk *cp);
};
struct crypto_backend {
struct crypto_hash *(*hash_open)(enum crypto_algo_hash hash);
struct crypto_pk *(*pk_open)(enum crypto_algo_pk pk, va_list vl);
struct crypto_pk *(*pk_open_priv)(enum crypto_algo_pk pk, va_list vl);
struct crypto_pk *(*pk_genkey)(enum crypto_algo_pk pk, va_list vl);
struct crypto_hash *(*hash_open)(enum crypto_algo_hash hash);
struct crypto_pk *(*pk_open)(enum crypto_algo_pk pk, va_list vl);
struct crypto_pk *(*pk_open_priv)(enum crypto_algo_pk pk, va_list vl);
struct crypto_pk *(*pk_genkey)(enum crypto_algo_pk pk, va_list vl);
};
struct crypto_backend *crypto_polarssl_init(void);

View file

@ -10,7 +10,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
@ -30,132 +30,132 @@
#include "mbedtls/sha1.h"
struct crypto_hash_polarssl {
struct crypto_hash ch;
mbedtls_sha1_context ctx;
struct crypto_hash ch;
mbedtls_sha1_context ctx;
};
static void crypto_hash_polarssl_close(struct crypto_hash *_ch)
{
struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch;
struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch;
free(ch);
free(ch);
}
static void crypto_hash_polarssl_write(struct crypto_hash *_ch, const unsigned char *buf, size_t len)
{
struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch;
struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch;
mbedtls_sha1_update(&(ch->ctx), buf, len);
mbedtls_sha1_update(&(ch->ctx), buf, len);
}
static unsigned char *crypto_hash_polarssl_read(struct crypto_hash *_ch)
{
struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch;
struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch;
static unsigned char sha1sum[20];
mbedtls_sha1_finish(&(ch->ctx), sha1sum);
return sha1sum;
static unsigned char sha1sum[20];
mbedtls_sha1_finish(&(ch->ctx), sha1sum);
return sha1sum;
}
static size_t crypto_hash_polarssl_get_size(const struct crypto_hash *ch)
{
if (ch->algo == HASH_SHA_1)
return 20;
else
return 0;
if (ch->algo == HASH_SHA_1)
return 20;
else
return 0;
}
static struct crypto_hash *crypto_hash_polarssl_open(enum crypto_algo_hash hash)
{
if (hash != HASH_SHA_1)
return NULL;
if (hash != HASH_SHA_1)
return NULL;
struct crypto_hash_polarssl *ch = malloc(sizeof(*ch));
struct crypto_hash_polarssl *ch = malloc(sizeof(*ch));
mbedtls_sha1_starts(&(ch->ctx));
mbedtls_sha1_starts(&(ch->ctx));
ch->ch.write = crypto_hash_polarssl_write;
ch->ch.read = crypto_hash_polarssl_read;
ch->ch.close = crypto_hash_polarssl_close;
ch->ch.get_size = crypto_hash_polarssl_get_size;
ch->ch.write = crypto_hash_polarssl_write;
ch->ch.read = crypto_hash_polarssl_read;
ch->ch.close = crypto_hash_polarssl_close;
ch->ch.get_size = crypto_hash_polarssl_get_size;
return &ch->ch;
return &ch->ch;
}
struct crypto_pk_polarssl {
struct crypto_pk cp;
mbedtls_rsa_context ctx;
struct crypto_pk cp;
mbedtls_rsa_context ctx;
};
static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl)
{
struct crypto_pk_polarssl *cp = malloc(sizeof(*cp));
memset(cp, 0x00, sizeof(*cp));
struct crypto_pk_polarssl *cp = malloc(sizeof(*cp));
memset(cp, 0x00, sizeof(*cp));
char *mod = va_arg(vl, char *); // N
int modlen = va_arg(vl, size_t);
char *exp = va_arg(vl, char *); // E
int explen = va_arg(vl, size_t);
char *mod = va_arg(vl, char *); // N
int modlen = va_arg(vl, size_t);
char *exp = va_arg(vl, char *); // E
int explen = va_arg(vl, size_t);
mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0);
mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0);
cp->ctx.len = modlen; // size(N) in bytes
mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen);
mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen);
cp->ctx.len = modlen; // size(N) in bytes
mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen);
mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen);
int res = mbedtls_rsa_check_pubkey(&cp->ctx);
if(res != 0) {
fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
free(cp);
return NULL;
}
int res = mbedtls_rsa_check_pubkey(&cp->ctx);
if(res != 0) {
fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
free(cp);
return NULL;
}
return &cp->cp;
return &cp->cp;
}
static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl)
{
struct crypto_pk_polarssl *cp = malloc(sizeof(*cp));
memset(cp, 0x00, sizeof(*cp));
char *mod = va_arg(vl, char *);
int modlen = va_arg(vl, size_t);
char *exp = va_arg(vl, char *);
int explen = va_arg(vl, size_t);
char *d = va_arg(vl, char *);
int dlen = va_arg(vl, size_t);
char *p = va_arg(vl, char *);
int plen = va_arg(vl, size_t);
char *q = va_arg(vl, char *);
int qlen = va_arg(vl, size_t);
char *dp = va_arg(vl, char *);
int dplen = va_arg(vl, size_t);
char *dq = va_arg(vl, char *);
int dqlen = va_arg(vl, size_t);
// calc QP via Q and P
// char *inv = va_arg(vl, char *);
// int invlen = va_arg(vl, size_t);
struct crypto_pk_polarssl *cp = malloc(sizeof(*cp));
memset(cp, 0x00, sizeof(*cp));
char *mod = va_arg(vl, char *);
int modlen = va_arg(vl, size_t);
char *exp = va_arg(vl, char *);
int explen = va_arg(vl, size_t);
char *d = va_arg(vl, char *);
int dlen = va_arg(vl, size_t);
char *p = va_arg(vl, char *);
int plen = va_arg(vl, size_t);
char *q = va_arg(vl, char *);
int qlen = va_arg(vl, size_t);
char *dp = va_arg(vl, char *);
int dplen = va_arg(vl, size_t);
char *dq = va_arg(vl, char *);
int dqlen = va_arg(vl, size_t);
// calc QP via Q and P
// char *inv = va_arg(vl, char *);
// int invlen = va_arg(vl, size_t);
mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0);
mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0);
cp->ctx.len = modlen; // size(N) in bytes
mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen);
mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen);
cp->ctx.len = modlen; // size(N) in bytes
mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen);
mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen);
mbedtls_mpi_read_binary(&cp->ctx.D, (const unsigned char *)d, dlen);
mbedtls_mpi_read_binary(&cp->ctx.P, (const unsigned char *)p, plen);
mbedtls_mpi_read_binary(&cp->ctx.Q, (const unsigned char *)q, qlen);
mbedtls_mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen);
mbedtls_mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen);
mbedtls_mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P);
mbedtls_mpi_read_binary(&cp->ctx.D, (const unsigned char *)d, dlen);
mbedtls_mpi_read_binary(&cp->ctx.P, (const unsigned char *)p, plen);
mbedtls_mpi_read_binary(&cp->ctx.Q, (const unsigned char *)q, qlen);
mbedtls_mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen);
mbedtls_mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen);
mbedtls_mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P);
int res = mbedtls_rsa_check_privkey(&cp->ctx);
if(res != 0) {
fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
free(cp);
return NULL;
}
int res = mbedtls_rsa_check_privkey(&cp->ctx);
if(res != 0) {
fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
free(cp);
return NULL;
}
return &cp->cp;
return &cp->cp;
}
static int myrand(void *rng_state, unsigned char *output, size_t len) {
@ -173,184 +173,184 @@ static int myrand(void *rng_state, unsigned char *output, size_t len) {
static struct crypto_pk *crypto_pk_polarssl_genkey_rsa(va_list vl)
{
struct crypto_pk_polarssl *cp = malloc(sizeof(*cp));
memset(cp, 0x00, sizeof(*cp));
struct crypto_pk_polarssl *cp = malloc(sizeof(*cp));
memset(cp, 0x00, sizeof(*cp));
int transient = va_arg(vl, int);
unsigned int nbits = va_arg(vl, unsigned int);
unsigned int exp = va_arg(vl, unsigned int);
int transient = va_arg(vl, int);
unsigned int nbits = va_arg(vl, unsigned int);
unsigned int exp = va_arg(vl, unsigned int);
if (transient) {
}
if (transient) {
}
int res = mbedtls_rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp);
if (res) {
fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits);
free(cp);
return NULL;
}
int res = mbedtls_rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp);
if (res) {
fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits);
free(cp);
return NULL;
}
return &cp->cp;
return &cp->cp;
}
static void crypto_pk_polarssl_close(struct crypto_pk *_cp)
{
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
mbedtls_rsa_free(&cp->ctx);
free(cp);
mbedtls_rsa_free(&cp->ctx);
free(cp);
}
static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, const unsigned char *buf, size_t len, size_t *clen)
{
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
int res;
unsigned char *result;
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
int res;
unsigned char *result;
*clen = 0;
size_t keylen = mbedtls_mpi_size(&cp->ctx.N);
*clen = 0;
size_t keylen = mbedtls_mpi_size(&cp->ctx.N);
result = malloc(keylen);
if (!result) {
printf("RSA encrypt failed. Can't allocate result memory.\n");
return NULL;
}
result = malloc(keylen);
if (!result) {
printf("RSA encrypt failed. Can't allocate result memory.\n");
return NULL;
}
res = mbedtls_rsa_public(&cp->ctx, buf, result);
if(res) {
printf("RSA encrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen);
free(result);
return NULL;
}
res = mbedtls_rsa_public(&cp->ctx, buf, result);
if(res) {
printf("RSA encrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen);
free(result);
return NULL;
}
*clen = keylen;
*clen = keylen;
return result;
return result;
}
static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, const unsigned char *buf, size_t len, size_t *clen)
{
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
int res;
unsigned char *result;
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
int res;
unsigned char *result;
*clen = 0;
size_t keylen = mbedtls_mpi_size(&cp->ctx.N);
*clen = 0;
size_t keylen = mbedtls_mpi_size(&cp->ctx.N);
result = malloc(keylen);
if (!result) {
printf("RSA encrypt failed. Can't allocate result memory.\n");
return NULL;
}
result = malloc(keylen);
if (!result) {
printf("RSA encrypt failed. Can't allocate result memory.\n");
return NULL;
}
res = mbedtls_rsa_private(&cp->ctx, NULL, NULL, buf, result); // CHECK???
if(res) {
printf("RSA decrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen);
free(result);
return NULL;
}
res = mbedtls_rsa_private(&cp->ctx, NULL, NULL, buf, result); // CHECK???
if(res) {
printf("RSA decrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen);
free(result);
return NULL;
}
*clen = keylen;
*clen = keylen;
return result;
return result;
}
static size_t crypto_pk_polarssl_get_nbits(const struct crypto_pk *_cp)
{
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
return cp->ctx.len * 8;
return cp->ctx.len * 8;
return 0;
}
static unsigned char *crypto_pk_polarssl_get_parameter(const struct crypto_pk *_cp, unsigned param, size_t *plen)
{
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
unsigned char *result = NULL;
switch(param){
// mod
case 0:
*plen = mbedtls_mpi_size(&cp->ctx.N);
result = malloc(*plen);
memset(result, 0x00, *plen);
mbedtls_mpi_write_binary(&cp->ctx.N, result, *plen);
break;
// exp
case 1:
*plen = mbedtls_mpi_size(&cp->ctx.E);
result = malloc(*plen);
memset(result, 0x00, *plen);
mbedtls_mpi_write_binary(&cp->ctx.E, result, *plen);
break;
default:
printf("Error get parameter. Param=%d", param);
break;
}
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
unsigned char *result = NULL;
switch(param){
// mod
case 0:
*plen = mbedtls_mpi_size(&cp->ctx.N);
result = malloc(*plen);
memset(result, 0x00, *plen);
mbedtls_mpi_write_binary(&cp->ctx.N, result, *plen);
break;
// exp
case 1:
*plen = mbedtls_mpi_size(&cp->ctx.E);
result = malloc(*plen);
memset(result, 0x00, *plen);
mbedtls_mpi_write_binary(&cp->ctx.E, result, *plen);
break;
default:
printf("Error get parameter. Param=%d", param);
break;
}
return result;
return result;
}
static struct crypto_pk *crypto_pk_polarssl_open(enum crypto_algo_pk pk, va_list vl)
{
struct crypto_pk *cp;
struct crypto_pk *cp;
if (pk == PK_RSA)
cp = crypto_pk_polarssl_open_rsa(vl);
else
return NULL;
if (pk == PK_RSA)
cp = crypto_pk_polarssl_open_rsa(vl);
else
return NULL;
cp->close = crypto_pk_polarssl_close;
cp->encrypt = crypto_pk_polarssl_encrypt;
cp->get_parameter = crypto_pk_polarssl_get_parameter;
cp->get_nbits = crypto_pk_polarssl_get_nbits;
cp->close = crypto_pk_polarssl_close;
cp->encrypt = crypto_pk_polarssl_encrypt;
cp->get_parameter = crypto_pk_polarssl_get_parameter;
cp->get_nbits = crypto_pk_polarssl_get_nbits;
return cp;
return cp;
}
static struct crypto_pk *crypto_pk_polarssl_open_priv(enum crypto_algo_pk pk, va_list vl)
{
struct crypto_pk *cp;
struct crypto_pk *cp;
if (pk == PK_RSA)
cp = crypto_pk_polarssl_open_priv_rsa(vl);
else
return NULL;
if (pk == PK_RSA)
cp = crypto_pk_polarssl_open_priv_rsa(vl);
else
return NULL;
cp->close = crypto_pk_polarssl_close;
cp->encrypt = crypto_pk_polarssl_encrypt;
cp->decrypt = crypto_pk_polarssl_decrypt;
cp->get_parameter = crypto_pk_polarssl_get_parameter;
cp->get_nbits = crypto_pk_polarssl_get_nbits;
cp->close = crypto_pk_polarssl_close;
cp->encrypt = crypto_pk_polarssl_encrypt;
cp->decrypt = crypto_pk_polarssl_decrypt;
cp->get_parameter = crypto_pk_polarssl_get_parameter;
cp->get_nbits = crypto_pk_polarssl_get_nbits;
return cp;
return cp;
}
static struct crypto_pk *crypto_pk_polarssl_genkey(enum crypto_algo_pk pk, va_list vl)
{
struct crypto_pk *cp;
struct crypto_pk *cp;
if (pk == PK_RSA)
cp = crypto_pk_polarssl_genkey_rsa(vl);
else
return NULL;
if (pk == PK_RSA)
cp = crypto_pk_polarssl_genkey_rsa(vl);
else
return NULL;
cp->close = crypto_pk_polarssl_close;
cp->encrypt = crypto_pk_polarssl_encrypt;
cp->decrypt = crypto_pk_polarssl_decrypt;
cp->get_parameter = crypto_pk_polarssl_get_parameter;
cp->get_nbits = crypto_pk_polarssl_get_nbits;
cp->close = crypto_pk_polarssl_close;
cp->encrypt = crypto_pk_polarssl_encrypt;
cp->decrypt = crypto_pk_polarssl_decrypt;
cp->get_parameter = crypto_pk_polarssl_get_parameter;
cp->get_nbits = crypto_pk_polarssl_get_nbits;
return cp;
return cp;
}
static struct crypto_backend crypto_polarssl_backend = {
.hash_open = crypto_hash_polarssl_open,
.pk_open = crypto_pk_polarssl_open,
.pk_open_priv = crypto_pk_polarssl_open_priv,
.pk_genkey = crypto_pk_polarssl_genkey,
.hash_open = crypto_hash_polarssl_open,
.pk_open = crypto_pk_polarssl_open,
.pk_open_priv = crypto_pk_polarssl_open_priv,
.pk_genkey = crypto_pk_polarssl_genkey,
};
struct crypto_backend *crypto_polarssl_init(void)
{
return &crypto_polarssl_backend;
return &crypto_polarssl_backend;
}

View file

@ -25,111 +25,111 @@
static size_t dol_calculate_len(const struct tlv *tlv, size_t data_len)
{
if (!tlv)
return 0;
if (!tlv)
return 0;
const unsigned char *buf = tlv->value;
size_t left = tlv->len;
size_t count = 0;
const unsigned char *buf = tlv->value;
size_t left = tlv->len;
size_t count = 0;
while (left) {
struct tlv tlv;
if (!tlv_parse_tl(&buf, &left, &tlv))
return 0;
while (left) {
struct tlv tlv;
if (!tlv_parse_tl(&buf, &left, &tlv))
return 0;
count += tlv.len;
count += tlv.len;
/* Last tag can be of variable length */
if (tlv.len == 0 && left == 0)
count = data_len;
}
/* Last tag can be of variable length */
if (tlv.len == 0 && left == 0)
count = data_len;
}
return count;
return count;
}
struct tlv *dol_process(const struct tlv *tlv, const struct tlvdb *tlvdb, tlv_tag_t tag)
{
size_t res_len;
if (!tlv || !(res_len = dol_calculate_len(tlv, 0))) {
struct tlv *res_tlv = malloc(sizeof(*res_tlv));
size_t res_len;
if (!tlv || !(res_len = dol_calculate_len(tlv, 0))) {
struct tlv *res_tlv = malloc(sizeof(*res_tlv));
res_tlv->tag = tag;
res_tlv->len = 0;
res_tlv->value = NULL;
res_tlv->tag = tag;
res_tlv->len = 0;
res_tlv->value = NULL;
return res_tlv;
}
return res_tlv;
}
struct tlv *res_tlv = malloc(sizeof(*res_tlv) + res_len);
if (!res_tlv)
return NULL;
struct tlv *res_tlv = malloc(sizeof(*res_tlv) + res_len);
if (!res_tlv)
return NULL;
const unsigned char *buf = tlv->value;
size_t left = tlv->len;
unsigned char *res = (unsigned char *)(res_tlv + 1);
size_t pos = 0;
const unsigned char *buf = tlv->value;
size_t left = tlv->len;
unsigned char *res = (unsigned char *)(res_tlv + 1);
size_t pos = 0;
while (left) {
struct tlv cur_tlv;
if (!tlv_parse_tl(&buf, &left, &cur_tlv) || pos + cur_tlv.len > res_len) {
free(res_tlv);
while (left) {
struct tlv cur_tlv;
if (!tlv_parse_tl(&buf, &left, &cur_tlv) || pos + cur_tlv.len > res_len) {
free(res_tlv);
return NULL;
}
return NULL;
}
const struct tlv *tag_tlv = tlvdb_get(tlvdb, cur_tlv.tag, NULL);
if (!tag_tlv) {
memset(res + pos, 0, cur_tlv.len);
} else if (tag_tlv->len > cur_tlv.len) {
memcpy(res + pos, tag_tlv->value, cur_tlv.len);
} else {
// FIXME: cn data should be padded with 0xFF !!!
memcpy(res + pos, tag_tlv->value, tag_tlv->len);
memset(res + pos + tag_tlv->len, 0, cur_tlv.len - tag_tlv->len);
}
pos += cur_tlv.len;
}
const struct tlv *tag_tlv = tlvdb_get(tlvdb, cur_tlv.tag, NULL);
if (!tag_tlv) {
memset(res + pos, 0, cur_tlv.len);
} else if (tag_tlv->len > cur_tlv.len) {
memcpy(res + pos, tag_tlv->value, cur_tlv.len);
} else {
// FIXME: cn data should be padded with 0xFF !!!
memcpy(res + pos, tag_tlv->value, tag_tlv->len);
memset(res + pos + tag_tlv->len, 0, cur_tlv.len - tag_tlv->len);
}
pos += cur_tlv.len;
}
res_tlv->tag = tag;
res_tlv->len = res_len;
res_tlv->value = res;
res_tlv->tag = tag;
res_tlv->len = res_len;
res_tlv->value = res;
return res_tlv;
return res_tlv;
}
struct tlvdb *dol_parse(const struct tlv *tlv, const unsigned char *data, size_t data_len)
{
if (!tlv)
return NULL;
if (!tlv)
return NULL;
const unsigned char *buf = tlv->value;
size_t left = tlv->len;
size_t res_len = dol_calculate_len(tlv, data_len);
size_t pos = 0;
struct tlvdb *db = NULL;
const unsigned char *buf = tlv->value;
size_t left = tlv->len;
size_t res_len = dol_calculate_len(tlv, data_len);
size_t pos = 0;
struct tlvdb *db = NULL;
if (res_len != data_len)
return NULL;
if (res_len != data_len)
return NULL;
while (left) {
struct tlv cur_tlv;
if (!tlv_parse_tl(&buf, &left, &cur_tlv) || pos + cur_tlv.len > res_len) {
tlvdb_free(db);
return NULL;
}
while (left) {
struct tlv cur_tlv;
if (!tlv_parse_tl(&buf, &left, &cur_tlv) || pos + cur_tlv.len > res_len) {
tlvdb_free(db);
return NULL;
}
/* Last tag can be of variable length */
if (cur_tlv.len == 0 && left == 0)
cur_tlv.len = res_len - pos;
/* Last tag can be of variable length */
if (cur_tlv.len == 0 && left == 0)
cur_tlv.len = res_len - pos;
struct tlvdb *tag_db = tlvdb_fixed(cur_tlv.tag, cur_tlv.len, data + pos);
if (!db)
db = tag_db;
else
tlvdb_add(db, tag_db);
struct tlvdb *tag_db = tlvdb_fixed(cur_tlv.tag, cur_tlv.len, data + pos);
if (!db)
db = tag_db;
else
tlvdb_add(db, tag_db);
pos += cur_tlv.len;
}
pos += cur_tlv.len;
}
return db;
return db;
}

View file

@ -20,40 +20,40 @@
#include "dump.h"
#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");}
#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");}
void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f)
{
int i;
int i;
if (!f)
f = stdout;
if (!f)
f = stdout;
for (i = 0; i < len; i ++)
fprintf(f, "%s%02hhX", i ? " " : "", ptr[i]);
for (i = 0; i < len; i ++)
fprintf(f, "%s%02hhX", i ? " " : "", ptr[i]);
}
void dump_buffer(const unsigned char *ptr, size_t len, FILE *f, int level)
{
int i, j;
int i, j;
if (!f)
f = stdout;
if (!f)
f = stdout;
for (i = 0; i < len; i += 16) {
PRINT_INDENT(level);
fprintf(f, "\t%02x:", i);
for (j = 0; j < 16; j++) {
if (i + j < len)
fprintf(f, " %02hhx", ptr[i + j]);
else
fprintf(f, " ");
}
fprintf(f, " |");
for (j = 0; j < 16 && i + j < len; j++) {
fprintf(f, "%c", (ptr[i+j] >= 0x20 && ptr[i+j] < 0x7f) ? ptr[i+j] : '.' );
}
fprintf(f, "\n");
}
for (i = 0; i < len; i += 16) {
PRINT_INDENT(level);
fprintf(f, "\t%02x:", i);
for (j = 0; j < 16; j++) {
if (i + j < len)
fprintf(f, " %02hhx", ptr[i + j]);
else
fprintf(f, " ");
}
fprintf(f, " |");
for (j = 0; j < 16 && i + j < len; j++) {
fprintf(f, "%c", (ptr[i+j] >= 0x20 && ptr[i+j] < 0x7f) ? ptr[i+j] : '.' );
}
fprintf(f, "\n");
}
}

View file

@ -31,488 +31,488 @@
#include <sys/types.h>
#define BCD(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
-1)
-1)
#define HEX(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \
((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : \
-1)
((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \
((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : \
-1)
#define TOHEX(v) ((v) < 10 ? (v) + '0' : (v) - 10 + 'a')
static ssize_t emv_pk_read_bin(char *buf, unsigned char *bin, size_t size, size_t *read)
{
size_t left = size;
char *p = buf;
while (*p && *p == ' ')
p++;
size_t left = size;
char *p = buf;
while (*p && *p == ' ')
p++;
while (left > 0) {
int c1, c2;
c1 = HEX(*p);
if (c1 == -1)
return -(p - buf);
p++;
c2 = HEX(*p);
if (c2 == -1)
return -(p - buf);
p++;
*bin = (c1 * 16 + c2);
bin ++;
left --;
if (*p == ':')
p++;
else if (read) {
*read = (size - left);
break;
} else if (left == 0)
break;
else
return -(p - buf);
}
while (left > 0) {
int c1, c2;
c1 = HEX(*p);
if (c1 == -1)
return -(p - buf);
p++;
c2 = HEX(*p);
if (c2 == -1)
return -(p - buf);
p++;
*bin = (c1 * 16 + c2);
bin ++;
left --;
if (*p == ':')
p++;
else if (read) {
*read = (size - left);
break;
} else if (left == 0)
break;
else
return -(p - buf);
}
while (*p && *p == ' ')
p++;
while (*p && *p == ' ')
p++;
p--;
p--;
return (p - buf);
return (p - buf);
}
static ssize_t emv_pk_read_ymv(char *buf, unsigned *ymv)
{
int i;
unsigned char temp[3];
char *p = buf;
int i;
unsigned char temp[3];
char *p = buf;
*ymv = 0;
*ymv = 0;
while (*p && *p == ' ')
p++;
while (*p && *p == ' ')
p++;
for (i = 0; i < 3; i++) {
int c1, c2;
c1 = BCD(*p);
if (c1 == -1)
return -(p - buf);
p++;
c2 = BCD(*p);
if (c2 == -1)
return -(p - buf);
p++;
temp[i] = (c1 * 16 + c2);
}
for (i = 0; i < 3; i++) {
int c1, c2;
c1 = BCD(*p);
if (c1 == -1)
return -(p - buf);
p++;
c2 = BCD(*p);
if (c2 == -1)
return -(p - buf);
p++;
temp[i] = (c1 * 16 + c2);
}
while (*p && *p == ' ')
p++;
while (*p && *p == ' ')
p++;
p--;
p--;
if (temp[1] > 0x12 || temp[2] > 0x31)
return -(p - buf);
if (temp[1] > 0x12 || temp[2] > 0x31)
return -(p - buf);
*ymv = (temp[0] * 0x10000 + temp[1] * 0x100 + temp[2]);
*ymv = (temp[0] * 0x10000 + temp[1] * 0x100 + temp[2]);
return (p - buf);
return (p - buf);
}
static ssize_t emv_pk_read_string(char *buf, char *str, size_t size)
{
char *p = buf;
while (*p && *p == ' ')
p++;
char *p = buf;
while (*p && *p == ' ')
p++;
while (size > 1) {
if (*p == ' ')
break;
else if (*p < 0x20 || *p >= 0x7f)
return -(p - buf);
*str = *p;
p++;
str ++;
size --;
}
while (size > 1) {
if (*p == ' ')
break;
else if (*p < 0x20 || *p >= 0x7f)
return -(p - buf);
*str = *p;
p++;
str ++;
size --;
}
*str = 0;
*str = 0;
while (*p && *p == ' ')
p++;
while (*p && *p == ' ')
p++;
p--;
p--;
return (p - buf);
return (p - buf);
}
struct emv_pk *emv_pk_parse_pk(char *buf)
{
struct emv_pk *r = calloc(1, sizeof(*r));
ssize_t l;
char temp[10];
struct emv_pk *r = calloc(1, sizeof(*r));
ssize_t l;
char temp[10];
l = emv_pk_read_bin(buf, r->rid, 5, NULL);
if (l <= 0)
goto out;
buf += l;
l = emv_pk_read_bin(buf, r->rid, 5, NULL);
if (l <= 0)
goto out;
buf += l;
l = emv_pk_read_bin(buf, &r->index, 1, NULL);
if (l <= 0)
goto out;
buf += l;
l = emv_pk_read_bin(buf, &r->index, 1, NULL);
if (l <= 0)
goto out;
buf += l;
l = emv_pk_read_ymv(buf, &r->expire);
if (l <= 0)
goto out;
buf += l;
l = emv_pk_read_ymv(buf, &r->expire);
if (l <= 0)
goto out;
buf += l;
l = emv_pk_read_string(buf, temp, sizeof(temp));
if (l <= 0)
goto out;
buf += l;
l = emv_pk_read_string(buf, temp, sizeof(temp));
if (l <= 0)
goto out;
buf += l;
if (!strcmp(temp, "rsa"))
r->pk_algo = PK_RSA;
else
goto out;
if (!strcmp(temp, "rsa"))
r->pk_algo = PK_RSA;
else
goto out;
l = emv_pk_read_bin(buf, r->exp, sizeof(r->exp), &r->elen);
if (l <= 0)
goto out;
buf += l;
l = emv_pk_read_bin(buf, r->exp, sizeof(r->exp), &r->elen);
if (l <= 0)
goto out;
buf += l;
r->modulus = malloc(2048/8);
l = emv_pk_read_bin(buf, r->modulus, 2048/8, &r->mlen);
if (l <= 0)
goto out2;
buf += l;
r->modulus = malloc(2048/8);
l = emv_pk_read_bin(buf, r->modulus, 2048/8, &r->mlen);
if (l <= 0)
goto out2;
buf += l;
l = emv_pk_read_string(buf, temp, sizeof(temp));
if (l <= 0)
goto out2;
buf += l;
l = emv_pk_read_string(buf, temp, sizeof(temp));
if (l <= 0)
goto out2;
buf += l;
if (!strcmp(temp, "sha1"))
r->hash_algo = HASH_SHA_1;
else
goto out2;
if (!strcmp(temp, "sha1"))
r->hash_algo = HASH_SHA_1;
else
goto out2;
l = emv_pk_read_bin(buf, r->hash, 20, NULL);
if (l <= 0)
goto out2;
l = emv_pk_read_bin(buf, r->hash, 20, NULL);
if (l <= 0)
goto out2;
return r;
return r;
out2:
free(r->modulus);
free(r->modulus);
out:
free(r);
return NULL;
free(r);
return NULL;
}
static size_t emv_pk_write_bin(char *out, size_t outlen, const unsigned char *buf, size_t len)
{
int i;
size_t pos = 0;
int i;
size_t pos = 0;
if (len == 0)
return 0;
if (outlen < len * 3)
return 0;
if (len == 0)
return 0;
if (outlen < len * 3)
return 0;
out[pos++] = TOHEX(buf[0] >> 4);
out[pos++] = TOHEX(buf[0] & 0xf);
for (i = 1; i < len; i++) {
out[pos++] = ':';
out[pos++] = TOHEX(buf[i] >> 4);
out[pos++] = TOHEX(buf[i] & 0xf);
}
out[pos++] = ' ';
out[pos++] = TOHEX(buf[0] >> 4);
out[pos++] = TOHEX(buf[0] & 0xf);
for (i = 1; i < len; i++) {
out[pos++] = ':';
out[pos++] = TOHEX(buf[i] >> 4);
out[pos++] = TOHEX(buf[i] & 0xf);
}
out[pos++] = ' ';
return pos;
return pos;
}
static size_t emv_pk_write_str(char *out, size_t outlen, const char *str)
{
size_t len = strlen(str);
size_t len = strlen(str);
if (len == 0)
return 0;
if (outlen < len)
return 0;
if (len == 0)
return 0;
if (outlen < len)
return 0;
memcpy(out, str, len);
memcpy(out, str, len);
return len;
return len;
}
char *emv_pk_dump_pk(const struct emv_pk *pk)
{
size_t outsize = 1024; /* should be enough */
char *out = malloc(outsize); /* should be enough */
size_t outpos = 0;
size_t rc;
size_t outsize = 1024; /* should be enough */
char *out = malloc(outsize); /* should be enough */
size_t outpos = 0;
size_t rc;
if (!out)
return NULL;
if (!out)
return NULL;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->rid, 5);
if (rc == 0)
goto err;
outpos += rc;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->rid, 5);
if (rc == 0)
goto err;
outpos += rc;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, &pk->index, 1);
if (rc == 0)
goto err;
outpos += rc;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, &pk->index, 1);
if (rc == 0)
goto err;
outpos += rc;
if (outpos + 7 > outsize)
goto err;
out[outpos++] = TOHEX((pk->expire >> 20) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 16) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 12) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 8 ) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 4 ) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 0 ) & 0xf);
out[outpos++] = ' ';
if (outpos + 7 > outsize)
goto err;
out[outpos++] = TOHEX((pk->expire >> 20) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 16) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 12) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 8 ) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 4 ) & 0xf);
out[outpos++] = TOHEX((pk->expire >> 0 ) & 0xf);
out[outpos++] = ' ';
if (pk->pk_algo == PK_RSA) {
rc = emv_pk_write_str(out + outpos, outsize - outpos, "rsa");
if (rc == 0)
goto err;
outpos += rc;
out[outpos++] = ' ';
} else {
if (outpos + 4 > outsize)
goto err;
out[outpos++] = '?';
out[outpos++] = '?';
out[outpos++] = TOHEX(pk->pk_algo >> 4);
out[outpos++] = TOHEX(pk->pk_algo & 0xf);
}
if (pk->pk_algo == PK_RSA) {
rc = emv_pk_write_str(out + outpos, outsize - outpos, "rsa");
if (rc == 0)
goto err;
outpos += rc;
out[outpos++] = ' ';
} else {
if (outpos + 4 > outsize)
goto err;
out[outpos++] = '?';
out[outpos++] = '?';
out[outpos++] = TOHEX(pk->pk_algo >> 4);
out[outpos++] = TOHEX(pk->pk_algo & 0xf);
}
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->exp, pk->elen);
if (rc == 0)
goto err;
outpos += rc;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->exp, pk->elen);
if (rc == 0)
goto err;
outpos += rc;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->modulus, pk->mlen);
if (rc == 0)
goto err;
outpos += rc;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->modulus, pk->mlen);
if (rc == 0)
goto err;
outpos += rc;
if (pk->hash_algo == HASH_SHA_1) {
rc = emv_pk_write_str(out + outpos, outsize - outpos, "sha1");
if (rc == 0)
goto err;
outpos += rc;
out[outpos++] = ' ';
} else {
if (outpos + 4 > outsize)
goto err;
out[outpos++] = '?';
out[outpos++] = '?';
out[outpos++] = TOHEX(pk->pk_algo >> 4);
out[outpos++] = TOHEX(pk->pk_algo & 0xf);
}
if (pk->hash_algo == HASH_SHA_1) {
rc = emv_pk_write_str(out + outpos, outsize - outpos, "sha1");
if (rc == 0)
goto err;
outpos += rc;
out[outpos++] = ' ';
} else {
if (outpos + 4 > outsize)
goto err;
out[outpos++] = '?';
out[outpos++] = '?';
out[outpos++] = TOHEX(pk->pk_algo >> 4);
out[outpos++] = TOHEX(pk->pk_algo & 0xf);
}
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->hash, 20);
if (rc == 0)
goto err;
outpos += rc;
rc = emv_pk_write_bin(out + outpos, outsize - outpos, pk->hash, 20);
if (rc == 0)
goto err;
outpos += rc;
out[outpos-1] = '\0';
out[outpos-1] = '\0';
return out;
return out;
err:
free(out);
return NULL;
free(out);
return NULL;
}
bool emv_pk_verify(const struct emv_pk *pk)
{
struct crypto_hash *ch = crypto_hash_open(pk->hash_algo);
if (!ch)
return false;
struct crypto_hash *ch = crypto_hash_open(pk->hash_algo);
if (!ch)
return false;
crypto_hash_write(ch, pk->rid, sizeof(pk->rid));
crypto_hash_write(ch, &pk->index, 1);
crypto_hash_write(ch, pk->modulus, pk->mlen);
crypto_hash_write(ch, pk->exp, pk->elen);
crypto_hash_write(ch, pk->rid, sizeof(pk->rid));
crypto_hash_write(ch, &pk->index, 1);
crypto_hash_write(ch, pk->modulus, pk->mlen);
crypto_hash_write(ch, pk->exp, pk->elen);
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
return false;
}
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
return false;
}
size_t hsize = crypto_hash_get_size(ch);
bool r = hsize && !memcmp(h, pk->hash, hsize) ? true : false;
size_t hsize = crypto_hash_get_size(ch);
bool r = hsize && !memcmp(h, pk->hash, hsize) ? true : false;
crypto_hash_close(ch);
crypto_hash_close(ch);
return r;
return r;
}
struct emv_pk *emv_pk_new(size_t modlen, size_t explen)
{
struct emv_pk *pk;
struct emv_pk *pk;
/* Not supported ATM */
if (explen > 3)
return NULL;
/* Not supported ATM */
if (explen > 3)
return NULL;
pk = calloc(1, sizeof(*pk));
if (!pk)
return NULL;
pk = calloc(1, sizeof(*pk));
if (!pk)
return NULL;
pk->mlen = modlen;
pk->elen = explen;
pk->mlen = modlen;
pk->elen = explen;
pk->modulus = calloc(modlen, 1);
if (!pk->modulus) {
free(pk);
pk = NULL;
}
pk->modulus = calloc(modlen, 1);
if (!pk->modulus) {
free(pk);
pk = NULL;
}
return pk;
return pk;
}
void emv_pk_free(struct emv_pk *pk)
{
if (!pk)
return;
if (!pk)
return;
free(pk->modulus);
free(pk);
free(pk->modulus);
free(pk);
}
static struct emv_pk *emv_pk_get_ca_pk_from_file(const char *fname,
const unsigned char *rid,
unsigned char idx)
const unsigned char *rid,
unsigned char idx)
{
if (!fname)
return NULL;
if (!fname)
return NULL;
FILE *f = fopen(fname, "r");
if (!f) {
perror("fopen");
return NULL;
}
FILE *f = fopen(fname, "r");
if (!f) {
perror("fopen");
return NULL;
}
while (!feof(f)) {
char buf[2048];
if (fgets(buf, sizeof(buf), f) == NULL)
break;
while (!feof(f)) {
char buf[2048];
if (fgets(buf, sizeof(buf), f) == NULL)
break;
struct emv_pk *pk = emv_pk_parse_pk(buf);
if (!pk)
continue;
if (memcmp(pk->rid, rid, 5) || pk->index != idx) {
emv_pk_free(pk);
continue;
}
struct emv_pk *pk = emv_pk_parse_pk(buf);
if (!pk)
continue;
if (memcmp(pk->rid, rid, 5) || pk->index != idx) {
emv_pk_free(pk);
continue;
}
fclose(f);
fclose(f);
return pk;
}
return pk;
}
fclose(f);
fclose(f);
return NULL;
return NULL;
}
char *emv_pk_get_ca_pk_file(const char *dirname, const unsigned char *rid, unsigned char idx)
{
if (!dirname)
dirname = ".";//openemv_config_get_str("capk.dir", NULL);
if (!dirname)
dirname = ".";//openemv_config_get_str("capk.dir", NULL);
char *filename;
int ret = asprintf(&filename, "%s/%02hhx%02hhx%02hhx%02hhx%02hhx_%02hhx.0",
dirname,
rid[0],
rid[1],
rid[2],
rid[3],
rid[4],
idx);
char *filename;
int ret = asprintf(&filename, "%s/%02hhx%02hhx%02hhx%02hhx%02hhx_%02hhx.0",
dirname,
rid[0],
rid[1],
rid[2],
rid[3],
rid[4],
idx);
if (ret <= 0)
return NULL;
if (ret <= 0)
return NULL;
return filename;
return filename;
}
char *emv_pk_get_ca_pk_rid_file(const char *dirname, const unsigned char *rid)
{
if (!dirname)
dirname = "."; //openemv_config_get_str("capk.dir", NULL);
if (!dirname)
dirname = "."; //openemv_config_get_str("capk.dir", NULL);
char *filename;
int ret = asprintf(&filename, "%s/%02hhx%02hhx%02hhx%02hhx%02hhx.pks",
dirname,
rid[0],
rid[1],
rid[2],
rid[3],
rid[4]);
char *filename;
int ret = asprintf(&filename, "%s/%02hhx%02hhx%02hhx%02hhx%02hhx.pks",
dirname,
rid[0],
rid[1],
rid[2],
rid[3],
rid[4]);
if (ret <= 0)
return NULL;
if (ret <= 0)
return NULL;
return filename;
return filename;
}
struct emv_pk *emv_pk_get_ca_pk(const unsigned char *rid, unsigned char idx)
{
struct emv_pk *pk = NULL;
struct emv_pk *pk = NULL;
/* if (!pk) {
char *fname = emv_pk_get_ca_pk_file(NULL, rid, idx);
if (fname) {
pk = emv_pk_get_ca_pk_from_file(fname, rid, idx);
free(fname);
}
}
/* if (!pk) {
char *fname = emv_pk_get_ca_pk_file(NULL, rid, idx);
if (fname) {
pk = emv_pk_get_ca_pk_from_file(fname, rid, idx);
free(fname);
}
}
if (!pk) {
char *fname = emv_pk_get_ca_pk_rid_file(NULL, rid);
if (fname) {
pk = emv_pk_get_ca_pk_from_file(fname, rid, idx);
free(fname);
}
}
if (!pk) {
char *fname = emv_pk_get_ca_pk_rid_file(NULL, rid);
if (fname) {
pk = emv_pk_get_ca_pk_from_file(fname, rid, idx);
free(fname);
}
}
*/
if (!pk) {
const char *relfname = "emv/capk.txt";
if (!pk) {
const char *relfname = "emv/capk.txt";
char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1];
strcpy(fname, get_my_executable_directory());
strcat(fname, relfname);
char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1];
strcpy(fname, get_my_executable_directory());
strcat(fname, relfname);
pk = emv_pk_get_ca_pk_from_file(fname, rid, idx);
}
if (!pk)
return NULL;
pk = emv_pk_get_ca_pk_from_file(fname, rid, idx);
}
if (!pk)
return NULL;
printf("Verifying CA PK for %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx %zd bits...",
pk->rid[0],
pk->rid[1],
pk->rid[2],
pk->rid[3],
pk->rid[4],
pk->index,
pk->mlen * 8);
if (emv_pk_verify(pk)) {
printf("OK\n");
printf("Verifying CA PK for %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx %zd bits...",
pk->rid[0],
pk->rid[1],
pk->rid[2],
pk->rid[3],
pk->rid[4],
pk->index,
pk->mlen * 8);
if (emv_pk_verify(pk)) {
printf("OK\n");
return pk;
}
return pk;
}
printf("Failed!\n");
emv_pk_free(pk);
printf("Failed!\n");
emv_pk_free(pk);
return NULL;
return NULL;
}

View file

@ -20,21 +20,21 @@
#include <stddef.h>
struct emv_pk {
unsigned char rid[5];
unsigned char index;
unsigned char serial[3];
unsigned char pan[10];
unsigned char hash_algo;
unsigned char pk_algo;
unsigned char hash[20];
unsigned char exp[3];
size_t elen;
size_t mlen;
unsigned char *modulus;
unsigned int expire;
unsigned char rid[5];
unsigned char index;
unsigned char serial[3];
unsigned char pan[10];
unsigned char hash_algo;
unsigned char pk_algo;
unsigned char hash[20];
unsigned char exp[3];
size_t elen;
size_t mlen;
unsigned char *modulus;
unsigned int expire;
};
#define EXPIRE(yy, mm, dd) 0x ## yy ## mm ## dd
#define EXPIRE(yy, mm, dd) 0x ## yy ## mm ## dd
struct emv_pk *emv_pk_parse_pk(char *buf);
struct emv_pk *emv_pk_new(size_t modlen, size_t explen);

View file

@ -29,7 +29,7 @@
static bool strictExecution = true;
void PKISetStrictExecution(bool se) {
strictExecution = se;
strictExecution = se;
}
static const unsigned char empty_tlv_value[] = {};
@ -38,551 +38,551 @@ static const struct tlv empty_tlv = {.tag = 0x0, .len = 0, .value = empty_tlv_va
static size_t emv_pki_hash_psn[256] = { 0, 0, 11, 2, 17, 2, };
static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk,
uint8_t msgtype,
size_t *len,
const struct tlv *cert_tlv,
int tlv_count,
... /* A list of tlv pointers */
)
uint8_t msgtype,
size_t *len,
const struct tlv *cert_tlv,
int tlv_count,
... /* A list of tlv pointers */
)
{
struct crypto_pk *kcp;
unsigned char *data;
size_t data_len;
va_list vl;
struct crypto_pk *kcp;
unsigned char *data;
size_t data_len;
va_list vl;
if (!enc_pk)
return NULL;
if (!enc_pk)
return NULL;
if (!cert_tlv) {
printf("ERROR: Can't find certificate\n");
return NULL;
}
if (!cert_tlv) {
printf("ERROR: Can't find certificate\n");
return NULL;
}
if (cert_tlv->len != enc_pk->mlen) {
printf("ERROR: Certificate length (%zu) not equal key length (%zu)\n", cert_tlv->len, enc_pk->mlen);
return NULL;
}
kcp = crypto_pk_open(enc_pk->pk_algo,
enc_pk->modulus, enc_pk->mlen,
enc_pk->exp, enc_pk->elen);
if (!kcp)
return NULL;
if (cert_tlv->len != enc_pk->mlen) {
printf("ERROR: Certificate length (%zu) not equal key length (%zu)\n", cert_tlv->len, enc_pk->mlen);
return NULL;
}
kcp = crypto_pk_open(enc_pk->pk_algo,
enc_pk->modulus, enc_pk->mlen,
enc_pk->exp, enc_pk->elen);
if (!kcp)
return NULL;
data = crypto_pk_encrypt(kcp, cert_tlv->value, cert_tlv->len, &data_len);
crypto_pk_close(kcp);
data = crypto_pk_encrypt(kcp, cert_tlv->value, cert_tlv->len, &data_len);
crypto_pk_close(kcp);
/* if (true){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}*/
/* if (true){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}*/
if (data[data_len-1] != 0xbc || data[0] != 0x6a || data[1] != msgtype) {
printf("ERROR: Certificate format\n");
free(data);
return NULL;
}
if (data[data_len-1] != 0xbc || data[0] != 0x6a || data[1] != msgtype) {
printf("ERROR: Certificate format\n");
free(data);
return NULL;
}
size_t hash_pos = emv_pki_hash_psn[msgtype];
if (hash_pos == 0 || hash_pos > data_len){
printf("ERROR: Cant get hash position in the certificate\n");
free(data);
return NULL;
}
size_t hash_pos = emv_pki_hash_psn[msgtype];
if (hash_pos == 0 || hash_pos > data_len){
printf("ERROR: Cant get hash position in the certificate\n");
free(data);
return NULL;
}
struct crypto_hash *ch;
ch = crypto_hash_open(data[hash_pos]);
if (!ch) {
printf("ERROR: Cant do hash\n");
free(data);
return NULL;
}
struct crypto_hash *ch;
ch = crypto_hash_open(data[hash_pos]);
if (!ch) {
printf("ERROR: Cant do hash\n");
free(data);
return NULL;
}
size_t hash_len = crypto_hash_get_size(ch);
crypto_hash_write(ch, data + 1, data_len - 2 - hash_len);
size_t hash_len = crypto_hash_get_size(ch);
crypto_hash_write(ch, data + 1, data_len - 2 - hash_len);
va_start(vl, tlv_count);
for (int i = 0; i < tlv_count; i++) {
const struct tlv *add_tlv = va_arg(vl, const struct tlv *);
if (!add_tlv)
continue;
va_start(vl, tlv_count);
for (int i = 0; i < tlv_count; i++) {
const struct tlv *add_tlv = va_arg(vl, const struct tlv *);
if (!add_tlv)
continue;
crypto_hash_write(ch, add_tlv->value, add_tlv->len);
}
va_end(vl);
crypto_hash_write(ch, add_tlv->value, add_tlv->len);
}
va_end(vl);
uint8_t hash[hash_len];
memset(hash, 0, hash_len);
memcpy(hash, crypto_hash_read(ch), hash_len);
if (memcmp(data + data_len - 1 - hash_len, hash, hash_len)) {
printf("ERROR: Calculated wrong hash\n");
printf("decoded: %s\n",sprint_hex(data + data_len - 1 - hash_len, hash_len));
printf("calculated: %s\n",sprint_hex(hash, hash_len));
uint8_t hash[hash_len];
memset(hash, 0, hash_len);
memcpy(hash, crypto_hash_read(ch), hash_len);
if (memcmp(data + data_len - 1 - hash_len, hash, hash_len)) {
printf("ERROR: Calculated wrong hash\n");
printf("decoded: %s\n",sprint_hex(data + data_len - 1 - hash_len, hash_len));
printf("calculated: %s\n",sprint_hex(hash, hash_len));
if (strictExecution) {
crypto_hash_close(ch);
free(data);
return NULL;
}
}
if (strictExecution) {
crypto_hash_close(ch);
free(data);
return NULL;
}
}
crypto_hash_close(ch);
crypto_hash_close(ch);
*len = data_len - hash_len - 1;
*len = data_len - hash_len - 1;
return data;
return data;
}
static unsigned emv_cn_length(const struct tlv *tlv)
{
int i;
int i;
for (i = 0; i < tlv->len; i++) {
unsigned char c = tlv->value[i];
for (i = 0; i < tlv->len; i++) {
unsigned char c = tlv->value[i];
if (c >> 4 == 0xf)
return 2 * i;
if (c >> 4 == 0xf)
return 2 * i;
if ((c & 0xf) == 0xf)
return 2 * i + 1;
}
if ((c & 0xf) == 0xf)
return 2 * i + 1;
}
return 2 * tlv->len;
return 2 * tlv->len;
}
static unsigned char emv_cn_get(const struct tlv *tlv, unsigned pos)
{
if (pos > tlv->len * 2)
return 0xf;
if (pos > tlv->len * 2)
return 0xf;
unsigned char c = tlv->value[pos / 2];
unsigned char c = tlv->value[pos / 2];
if (pos % 2)
return c & 0xf;
else
return c >> 4;
if (pos % 2)
return c & 0xf;
else
return c >> 4;
}
static struct emv_pk *emv_pki_decode_key_ex(const struct emv_pk *enc_pk,
unsigned char msgtype,
const struct tlv *pan_tlv,
const struct tlv *cert_tlv,
const struct tlv *exp_tlv,
const struct tlv *rem_tlv,
const struct tlv *add_tlv,
const struct tlv *sdatl_tlv,
bool showData
)
unsigned char msgtype,
const struct tlv *pan_tlv,
const struct tlv *cert_tlv,
const struct tlv *exp_tlv,
const struct tlv *rem_tlv,
const struct tlv *add_tlv,
const struct tlv *sdatl_tlv,
bool showData
)
{
size_t pan_length;
unsigned char *data;
size_t data_len;
size_t pk_len;
size_t pan_length;
unsigned char *data;
size_t data_len;
size_t pk_len;
if (!cert_tlv || !exp_tlv || !pan_tlv)
return NULL;
if (!cert_tlv || !exp_tlv || !pan_tlv)
return NULL;
if (!rem_tlv)
rem_tlv = &empty_tlv;
if (!rem_tlv)
rem_tlv = &empty_tlv;
if (msgtype == 2)
pan_length = 4;
else if (msgtype == 4)
pan_length = 10;
else {
printf("ERROR: Message type must be 2 or 4\n");
return NULL;
}
if (msgtype == 2)
pan_length = 4;
else if (msgtype == 4)
pan_length = 10;
else {
printf("ERROR: Message type must be 2 or 4\n");
return NULL;
}
data = emv_pki_decode_message(enc_pk, msgtype, &data_len,
cert_tlv,
5,
rem_tlv,
exp_tlv,
add_tlv,
sdatl_tlv,
NULL);
if (!data || data_len < 11 + pan_length) {
printf("ERROR: Can't decode message\n");
return NULL;
}
data = emv_pki_decode_message(enc_pk, msgtype, &data_len,
cert_tlv,
5,
rem_tlv,
exp_tlv,
add_tlv,
sdatl_tlv,
NULL);
if (!data || data_len < 11 + pan_length) {
printf("ERROR: Can't decode message\n");
return NULL;
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
/* Perform the rest of checks here */
/* Perform the rest of checks here */
struct tlv pan2_tlv = {
.tag = 0x5a,
.len = pan_length,
.value = &data[2],
};
unsigned pan_len = emv_cn_length(pan_tlv);
unsigned pan2_len = emv_cn_length(&pan2_tlv);
struct tlv pan2_tlv = {
.tag = 0x5a,
.len = pan_length,
.value = &data[2],
};
unsigned pan_len = emv_cn_length(pan_tlv);
unsigned pan2_len = emv_cn_length(&pan2_tlv);
if (((msgtype == 2) && (pan2_len < 4 || pan2_len > pan_len)) ||
((msgtype == 4) && (pan2_len != pan_len))) {
printf("ERROR: Invalid PAN lengths\n");
free(data);
if (((msgtype == 2) && (pan2_len < 4 || pan2_len > pan_len)) ||
((msgtype == 4) && (pan2_len != pan_len))) {
printf("ERROR: Invalid PAN lengths\n");
free(data);
return NULL;
}
return NULL;
}
unsigned i;
for (i = 0; i < pan2_len; i++)
if (emv_cn_get(pan_tlv, i) != emv_cn_get(&pan2_tlv, i)) {
printf("ERROR: PAN data mismatch\n");
printf("tlv pan=%s\n", sprint_hex(pan_tlv->value, pan_tlv->len));
printf("cert pan=%s\n", sprint_hex(pan2_tlv.value, pan2_tlv.len));
free(data);
unsigned i;
for (i = 0; i < pan2_len; i++)
if (emv_cn_get(pan_tlv, i) != emv_cn_get(&pan2_tlv, i)) {
printf("ERROR: PAN data mismatch\n");
printf("tlv pan=%s\n", sprint_hex(pan_tlv->value, pan_tlv->len));
printf("cert pan=%s\n", sprint_hex(pan2_tlv.value, pan2_tlv.len));
free(data);
return NULL;
}
return NULL;
}
pk_len = data[9 + pan_length];
if (pk_len > data_len - 11 - pan_length + rem_tlv->len) {
printf("ERROR: Invalid pk length\n");
free(data);
return NULL;
}
pk_len = data[9 + pan_length];
if (pk_len > data_len - 11 - pan_length + rem_tlv->len) {
printf("ERROR: Invalid pk length\n");
free(data);
return NULL;
}
if (exp_tlv->len != data[10 + pan_length]) {
free(data);
return NULL;
}
if (exp_tlv->len != data[10 + pan_length]) {
free(data);
return NULL;
}
struct emv_pk *pk = emv_pk_new(pk_len, exp_tlv->len);
struct emv_pk *pk = emv_pk_new(pk_len, exp_tlv->len);
memcpy(pk->rid, enc_pk->rid, 5);
pk->index = enc_pk->index;
memcpy(pk->rid, enc_pk->rid, 5);
pk->index = enc_pk->index;
pk->hash_algo = data[7 + pan_length];
pk->pk_algo = data[8 + pan_length];
pk->expire = (data[3 + pan_length] << 16) | (data[2 + pan_length] << 8) | 0x31;
memcpy(pk->serial, data + 4 + pan_length, 3);
memcpy(pk->pan, data + 2, pan_length);
memset(pk->pan + pan_length, 0xff, 10 - pan_length);
pk->hash_algo = data[7 + pan_length];
pk->pk_algo = data[8 + pan_length];
pk->expire = (data[3 + pan_length] << 16) | (data[2 + pan_length] << 8) | 0x31;
memcpy(pk->serial, data + 4 + pan_length, 3);
memcpy(pk->pan, data + 2, pan_length);
memset(pk->pan + pan_length, 0xff, 10 - pan_length);
memcpy(pk->modulus, data + 11 + pan_length,
pk_len < data_len - (11 + pan_length) ?
pk_len :
data_len - (11 + pan_length));
memcpy(pk->modulus + data_len - (11 + pan_length), rem_tlv->value, rem_tlv->len);
memcpy(pk->exp, exp_tlv->value, exp_tlv->len);
memcpy(pk->modulus, data + 11 + pan_length,
pk_len < data_len - (11 + pan_length) ?
pk_len :
data_len - (11 + pan_length));
memcpy(pk->modulus + data_len - (11 + pan_length), rem_tlv->value, rem_tlv->len);
memcpy(pk->exp, exp_tlv->value, exp_tlv->len);
free(data);
free(data);
return pk;
return pk;
}
static struct emv_pk *emv_pki_decode_key(const struct emv_pk *enc_pk,
unsigned char msgtype,
const struct tlv *pan_tlv,
const struct tlv *cert_tlv,
const struct tlv *exp_tlv,
const struct tlv *rem_tlv,
const struct tlv *add_tlv,
const struct tlv *sdatl_tlv
) {
return emv_pki_decode_key_ex(enc_pk, msgtype, pan_tlv, cert_tlv, exp_tlv, rem_tlv, add_tlv, sdatl_tlv, false);
unsigned char msgtype,
const struct tlv *pan_tlv,
const struct tlv *cert_tlv,
const struct tlv *exp_tlv,
const struct tlv *rem_tlv,
const struct tlv *add_tlv,
const struct tlv *sdatl_tlv
) {
return emv_pki_decode_key_ex(enc_pk, msgtype, pan_tlv, cert_tlv, exp_tlv, rem_tlv, add_tlv, sdatl_tlv, false);
}
struct emv_pk *emv_pki_recover_issuer_cert(const struct emv_pk *pk, struct tlvdb *db)
{
return emv_pki_decode_key(pk, 2,
tlvdb_get(db, 0x5a, NULL),
tlvdb_get(db, 0x90, NULL),
tlvdb_get(db, 0x9f32, NULL),
tlvdb_get(db, 0x92, NULL),
NULL,
NULL);
return emv_pki_decode_key(pk, 2,
tlvdb_get(db, 0x5a, NULL),
tlvdb_get(db, 0x90, NULL),
tlvdb_get(db, 0x9f32, NULL),
tlvdb_get(db, 0x92, NULL),
NULL,
NULL);
}
struct emv_pk *emv_pki_recover_icc_cert(const struct emv_pk *pk, struct tlvdb *db, const struct tlv *sda_tlv)
{
size_t sdatl_len;
unsigned char *sdatl = emv_pki_sdatl_fill(db, &sdatl_len);
struct tlv sda_tdata = {
.tag = 0x00, // dummy tag
.len = sdatl_len,
.value = sdatl
};
size_t sdatl_len;
unsigned char *sdatl = emv_pki_sdatl_fill(db, &sdatl_len);
struct tlv sda_tdata = {
.tag = 0x00, // dummy tag
.len = sdatl_len,
.value = sdatl
};
struct emv_pk *res = emv_pki_decode_key(pk, 4,
tlvdb_get(db, 0x5a, NULL),
tlvdb_get(db, 0x9f46, NULL),
tlvdb_get(db, 0x9f47, NULL),
tlvdb_get(db, 0x9f48, NULL),
sda_tlv,
&sda_tdata);
struct emv_pk *res = emv_pki_decode_key(pk, 4,
tlvdb_get(db, 0x5a, NULL),
tlvdb_get(db, 0x9f46, NULL),
tlvdb_get(db, 0x9f47, NULL),
tlvdb_get(db, 0x9f48, NULL),
sda_tlv,
&sda_tdata);
free(sdatl); // malloc here: emv_pki_sdatl_fill
return res;
free(sdatl); // malloc here: emv_pki_sdatl_fill
return res;
}
struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb *db)
{
return emv_pki_decode_key(pk, 4,
tlvdb_get(db, 0x5a, NULL),
tlvdb_get(db, 0x9f2d, NULL),
tlvdb_get(db, 0x9f2e, NULL),
tlvdb_get(db, 0x9f2f, NULL),
NULL,
NULL);
return emv_pki_decode_key(pk, 4,
tlvdb_get(db, 0x5a, NULL),
tlvdb_get(db, 0x9f2d, NULL),
tlvdb_get(db, 0x9f2e, NULL),
tlvdb_get(db, 0x9f2f, NULL),
NULL,
NULL);
}
unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len) {
uint8_t buf[2048] = {0};
size_t len = 0;
uint8_t buf[2048] = {0};
size_t len = 0;
*sdatl_len = 0;
*sdatl_len = 0;
const struct tlv *sda_tl = tlvdb_get(db, 0x9f4a, NULL);
if (!sda_tl || sda_tl->len <= 0)
return NULL;
const struct tlv *sda_tl = tlvdb_get(db, 0x9f4a, NULL);
if (!sda_tl || sda_tl->len <= 0)
return NULL;
for (int i = 0; i < sda_tl->len; i++) {
uint32_t tag = sda_tl->value[i]; // here may be multibyte, but now not
const struct tlv *elm = tlvdb_get(db, tag, NULL);
if (elm) {
memcpy(&buf[len], elm->value, elm->len);
len += elm->len;
}
}
for (int i = 0; i < sda_tl->len; i++) {
uint32_t tag = sda_tl->value[i]; // here may be multibyte, but now not
const struct tlv *elm = tlvdb_get(db, tag, NULL);
if (elm) {
memcpy(&buf[len], elm->value, elm->len);
len += elm->len;
}
}
if (len) {
*sdatl_len = len;
unsigned char *value = malloc(len);
memcpy(value, buf, len);
return value;
}
if (len) {
*sdatl_len = len;
unsigned char *value = malloc(len);
memcpy(value, buf, len);
return value;
}
return NULL;
return NULL;
}
struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv, bool showData)
{
size_t data_len;
size_t data_len;
// Static Data Authentication Tag List
size_t sdatl_len;
unsigned char *sdatl = emv_pki_sdatl_fill(db, &sdatl_len);
struct tlv sda_tdata = {
.tag = 0x00, // dummy tag
.len = sdatl_len,
.value = sdatl
};
// Static Data Authentication Tag List
size_t sdatl_len;
unsigned char *sdatl = emv_pki_sdatl_fill(db, &sdatl_len);
struct tlv sda_tdata = {
.tag = 0x00, // dummy tag
.len = sdatl_len,
.value = sdatl
};
unsigned char *data = emv_pki_decode_message(enc_pk, 3, &data_len,
tlvdb_get(db, 0x93, NULL),
3,
sda_tlv,
&sda_tdata,
NULL);
unsigned char *data = emv_pki_decode_message(enc_pk, 3, &data_len,
tlvdb_get(db, 0x93, NULL),
3,
sda_tlv,
&sda_tdata,
NULL);
free(sdatl); // malloc here: emv_pki_sdatl_fill
free(sdatl); // malloc here: emv_pki_sdatl_fill
if (!data || data_len < 5)
return NULL;
if (!data || data_len < 5)
return NULL;
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
struct tlvdb *dac_db = tlvdb_fixed(0x9f45, 2, data+3);
struct tlvdb *dac_db = tlvdb_fixed(0x9f45, 2, data+3);
free(data);
free(data);
return dac_db;
return dac_db;
}
struct tlvdb *emv_pki_recover_dac(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv) {
return emv_pki_recover_dac_ex(enc_pk, db, sda_tlv, false);
return emv_pki_recover_dac_ex(enc_pk, db, sda_tlv, false);
}
struct tlvdb *emv_pki_recover_idn(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *dyn_tlv) {
return emv_pki_recover_idn_ex(enc_pk, db, dyn_tlv, false);
return emv_pki_recover_idn_ex(enc_pk, db, dyn_tlv, false);
}
struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *dyn_tlv, bool showData)
{
size_t data_len;
unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
tlvdb_get(db, 0x9f4b, NULL),
2,
dyn_tlv,
NULL);
size_t data_len;
unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
tlvdb_get(db, 0x9f4b, NULL),
2,
dyn_tlv,
NULL);
if (!data || data_len < 3)
return NULL;
if (!data || data_len < 3)
return NULL;
if (data[3] < 2 || data[3] > data_len - 3) {
free(data);
return NULL;
}
if (data[3] < 2 || data[3] > data_len - 3) {
free(data);
return NULL;
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
size_t idn_len = data[4];
if (idn_len > data[3] - 1) {
free(data);
return NULL;
}
size_t idn_len = data[4];
if (idn_len > data[3] - 1) {
free(data);
return NULL;
}
// 9f4c ICC Dynamic Number
struct tlvdb *idn_db = tlvdb_fixed(0x9f4c, idn_len, data + 5);
// 9f4c ICC Dynamic Number
struct tlvdb *idn_db = tlvdb_fixed(0x9f4c, idn_len, data + 5);
free(data);
free(data);
return idn_db;
return idn_db;
}
struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, bool showData)
{
size_t data_len;
unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
tlvdb_get(db, 0x9f4b, NULL),
5,
tlvdb_get(db, 0x9f37, NULL),
tlvdb_get(db, 0x9f02, NULL),
tlvdb_get(db, 0x5f2a, NULL),
tlvdb_get(db, 0x9f69, NULL),
NULL);
size_t data_len;
unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
tlvdb_get(db, 0x9f4b, NULL),
5,
tlvdb_get(db, 0x9f37, NULL),
tlvdb_get(db, 0x9f02, NULL),
tlvdb_get(db, 0x5f2a, NULL),
tlvdb_get(db, 0x9f69, NULL),
NULL);
if (!data || data_len < 3)
return NULL;
if (!data || data_len < 3)
return NULL;
if (data[3] < 2 || data[3] > data_len - 3) {
free(data);
return NULL;
}
if (data[3] < 2 || data[3] > data_len - 3) {
free(data);
return NULL;
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
size_t idn_len = data[4];
if (idn_len > data[3] - 1) {
free(data);
return NULL;
}
size_t idn_len = data[4];
if (idn_len > data[3] - 1) {
free(data);
return NULL;
}
// 9f36 Application Transaction Counter (ATC)
struct tlvdb *atc_db = tlvdb_fixed(0x9f36, idn_len, data + 5);
// 9f36 Application Transaction Counter (ATC)
struct tlvdb *atc_db = tlvdb_fixed(0x9f36, idn_len, data + 5);
free(data);
free(data);
return atc_db;
return atc_db;
}
static bool tlv_hash(void *data, const struct tlv *tlv, int level, bool is_leaf)
{
struct crypto_hash *ch = data;
size_t tag_len;
unsigned char *tag;
struct crypto_hash *ch = data;
size_t tag_len;
unsigned char *tag;
if (tlv_is_constructed(tlv))
return true;
if (tlv_is_constructed(tlv))
return true;
if (tlv->tag == 0x9f4b)
return true;
if (tlv->tag == 0x9f4b)
return true;
tag = tlv_encode(tlv, &tag_len);
crypto_hash_write(ch, tag, tag_len);
free(tag);
tag = tlv_encode(tlv, &tag_len);
crypto_hash_write(ch, tag, tag_len);
free(tag);
return true;
return true;
}
struct tlvdb *emv_pki_perform_cda(const struct emv_pk *enc_pk, const struct tlvdb *db,
const struct tlvdb *this_db,
const struct tlv *pdol_data_tlv,
const struct tlv *crm1_tlv,
const struct tlv *crm2_tlv)
const struct tlvdb *this_db,
const struct tlv *pdol_data_tlv,
const struct tlv *crm1_tlv,
const struct tlv *crm2_tlv)
{
return emv_pki_perform_cda_ex(enc_pk, db, this_db, pdol_data_tlv, crm1_tlv, crm2_tlv, false);
return emv_pki_perform_cda_ex(enc_pk, db, this_db, pdol_data_tlv, crm1_tlv, crm2_tlv, false);
}
struct tlvdb *emv_pki_perform_cda_ex(const struct emv_pk *enc_pk, const struct tlvdb *db,
const struct tlvdb *this_db, // AC TLV result
const struct tlv *pdol_data_tlv, // PDOL
const struct tlv *crm1_tlv, // CDOL1
const struct tlv *crm2_tlv, // CDOL2
bool showData)
const struct tlvdb *this_db, // AC TLV result
const struct tlv *pdol_data_tlv, // PDOL
const struct tlv *crm1_tlv, // CDOL1
const struct tlv *crm2_tlv, // CDOL2
bool showData)
{
const struct tlv *un_tlv = tlvdb_get(db, 0x9f37, NULL);
const struct tlv *cid_tlv = tlvdb_get(this_db, 0x9f27, NULL);
const struct tlv *un_tlv = tlvdb_get(db, 0x9f37, NULL);
const struct tlv *cid_tlv = tlvdb_get(this_db, 0x9f27, NULL);
if (!un_tlv || !cid_tlv)
return NULL;
if (!un_tlv || !cid_tlv)
return NULL;
size_t data_len = 0;
unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
tlvdb_get(this_db, 0x9f4b, NULL),
2,
un_tlv,
NULL);
if (!data || data_len < 3) {
printf("ERROR: can't decode message. len %zu\n", data_len);
return NULL;
}
size_t data_len = 0;
unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
tlvdb_get(this_db, 0x9f4b, NULL),
2,
un_tlv,
NULL);
if (!data || data_len < 3) {
printf("ERROR: can't decode message. len %zu\n", data_len);
return NULL;
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
if (data[3] < 30 || data[3] > data_len - 4) {
printf("ERROR: Invalid data length\n");
free(data);
return NULL;
}
if (data[3] < 30 || data[3] > data_len - 4) {
printf("ERROR: Invalid data length\n");
free(data);
return NULL;
}
if (!cid_tlv || cid_tlv->len != 1 || cid_tlv->value[0] != data[5 + data[4]]) {
printf("ERROR: CID mismatch\n");
free(data);
return NULL;
}
if (!cid_tlv || cid_tlv->len != 1 || cid_tlv->value[0] != data[5 + data[4]]) {
printf("ERROR: CID mismatch\n");
free(data);
return NULL;
}
struct crypto_hash *ch;
ch = crypto_hash_open(enc_pk->hash_algo);
if (!ch) {
printf("ERROR: can't create hash\n");
free(data);
return NULL;
}
struct crypto_hash *ch;
ch = crypto_hash_open(enc_pk->hash_algo);
if (!ch) {
printf("ERROR: can't create hash\n");
free(data);
return NULL;
}
if (pdol_data_tlv)
crypto_hash_write(ch, pdol_data_tlv->value, pdol_data_tlv->len);
if (crm1_tlv)
crypto_hash_write(ch, crm1_tlv->value, crm1_tlv->len);
if (crm2_tlv)
crypto_hash_write(ch, crm2_tlv->value, crm2_tlv->len);
if (pdol_data_tlv)
crypto_hash_write(ch, pdol_data_tlv->value, pdol_data_tlv->len);
if (crm1_tlv)
crypto_hash_write(ch, crm1_tlv->value, crm1_tlv->len);
if (crm2_tlv)
crypto_hash_write(ch, crm2_tlv->value, crm2_tlv->len);
tlvdb_visit(this_db, tlv_hash, ch, 0);
tlvdb_visit(this_db, tlv_hash, ch, 0);
if (memcmp(data + 5 + data[4] + 1 + 8, crypto_hash_read(ch), 20)) {
printf("ERROR: calculated hash error\n");
crypto_hash_close(ch);
free(data);
return NULL;
}
crypto_hash_close(ch);
if (memcmp(data + 5 + data[4] + 1 + 8, crypto_hash_read(ch), 20)) {
printf("ERROR: calculated hash error\n");
crypto_hash_close(ch);
free(data);
return NULL;
}
crypto_hash_close(ch);
size_t idn_len = data[4];
if (idn_len > data[3] - 1) {
printf("ERROR: Invalid IDN length\n");
free(data);
return NULL;
}
size_t idn_len = data[4];
if (idn_len > data[3] - 1) {
printf("ERROR: Invalid IDN length\n");
free(data);
return NULL;
}
struct tlvdb *idn_db = tlvdb_fixed(0x9f4c, idn_len, data + 5);
free(data);
struct tlvdb *idn_db = tlvdb_fixed(0x9f4c, idn_len, data + 5);
free(data);
return idn_db;
return idn_db;
}

View file

@ -34,15 +34,15 @@ struct tlvdb *emv_pki_recover_idn(const struct emv_pk *pk, const struct tlvdb *d
struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *pk, const struct tlvdb *db, const struct tlv *dyn_tlv, bool showData);
struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, bool showData);
struct tlvdb *emv_pki_perform_cda(const struct emv_pk *enc_pk, const struct tlvdb *db,
const struct tlvdb *this_db,
const struct tlv *pdol_data_tlv,
const struct tlv *crm1_tlv,
const struct tlv *crm2_tlv);
const struct tlvdb *this_db,
const struct tlv *pdol_data_tlv,
const struct tlv *crm1_tlv,
const struct tlv *crm2_tlv);
struct tlvdb *emv_pki_perform_cda_ex(const struct emv_pk *enc_pk, const struct tlvdb *db,
const struct tlvdb *this_db,
const struct tlv *pdol_data_tlv,
const struct tlv *crm1_tlv,
const struct tlv *crm2_tlv,
bool showData);
const struct tlvdb *this_db,
const struct tlv *pdol_data_tlv,
const struct tlv *crm1_tlv,
const struct tlv *crm2_tlv,
bool showData);
#endif

View file

@ -25,259 +25,259 @@
#include <stdarg.h>
struct emv_pk *emv_pki_make_ca(const struct crypto_pk *cp,
const unsigned char *rid, unsigned char index,
unsigned int expire, enum crypto_algo_hash hash_algo)
const unsigned char *rid, unsigned char index,
unsigned int expire, enum crypto_algo_hash hash_algo)
{
size_t modlen, explen;
unsigned char *mod, *exp;
size_t modlen, explen;
unsigned char *mod, *exp;
if (!rid)
return NULL;
if (!rid)
return NULL;
mod = crypto_pk_get_parameter(cp, 0, &modlen);
exp = crypto_pk_get_parameter(cp, 1, &explen);
mod = crypto_pk_get_parameter(cp, 0, &modlen);
exp = crypto_pk_get_parameter(cp, 1, &explen);
if (!mod || !modlen || !exp || !explen) {
free(mod);
free(exp);
if (!mod || !modlen || !exp || !explen) {
free(mod);
free(exp);
return NULL;
}
return NULL;
}
struct emv_pk *pk = emv_pk_new(modlen, explen);
memcpy(pk->rid, rid, 5);
pk->index = index;
pk->expire = expire;
pk->pk_algo = crypto_pk_get_algo(cp);
pk->hash_algo = hash_algo;
memcpy(pk->modulus, mod, modlen);
memcpy(pk->exp, exp, explen);
struct emv_pk *pk = emv_pk_new(modlen, explen);
memcpy(pk->rid, rid, 5);
pk->index = index;
pk->expire = expire;
pk->pk_algo = crypto_pk_get_algo(cp);
pk->hash_algo = hash_algo;
memcpy(pk->modulus, mod, modlen);
memcpy(pk->exp, exp, explen);
free(mod);
free(exp);
free(mod);
free(exp);
struct crypto_hash *ch = crypto_hash_open(pk->hash_algo);
if (!ch) {
emv_pk_free(pk);
return false;
}
struct crypto_hash *ch = crypto_hash_open(pk->hash_algo);
if (!ch) {
emv_pk_free(pk);
return false;
}
crypto_hash_write(ch, pk->rid, sizeof(pk->rid));
crypto_hash_write(ch, &pk->index, 1);
crypto_hash_write(ch, pk->modulus, pk->mlen);
crypto_hash_write(ch, pk->exp, pk->elen);
crypto_hash_write(ch, pk->rid, sizeof(pk->rid));
crypto_hash_write(ch, &pk->index, 1);
crypto_hash_write(ch, pk->modulus, pk->mlen);
crypto_hash_write(ch, pk->exp, pk->elen);
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
emv_pk_free(pk);
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
emv_pk_free(pk);
return NULL;
}
return NULL;
}
memcpy(pk->hash, h, crypto_hash_get_size(ch));
crypto_hash_close(ch);
memcpy(pk->hash, h, crypto_hash_get_size(ch));
crypto_hash_close(ch);
return pk;
return pk;
}
static struct tlvdb *emv_pki_sign_message(const struct crypto_pk *cp,
tlv_tag_t cert_tag, tlv_tag_t rem_tag,
const unsigned char *msg, size_t msg_len,
... /* A list of tlv pointers, end with NULL */
)
tlv_tag_t cert_tag, tlv_tag_t rem_tag,
const unsigned char *msg, size_t msg_len,
... /* A list of tlv pointers, end with NULL */
)
{
size_t tmp_len = (crypto_pk_get_nbits(cp) + 7) / 8;
unsigned char *tmp = malloc(tmp_len);
if (!tmp)
return NULL;
size_t tmp_len = (crypto_pk_get_nbits(cp) + 7) / 8;
unsigned char *tmp = malloc(tmp_len);
if (!tmp)
return NULL;
// XXX
struct crypto_hash *ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(tmp);
// XXX
struct crypto_hash *ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(tmp);
return NULL;
}
return NULL;
}
tmp[0] = 0x6a;
tmp[tmp_len - 1] = 0xbc;
tmp[0] = 0x6a;
tmp[tmp_len - 1] = 0xbc;
const unsigned char *rem;
size_t rem_len;
size_t hash_len = crypto_hash_get_size(ch);
size_t part_len = tmp_len - 2 - hash_len;
if (part_len < msg_len) {
memcpy(tmp + 1, msg, part_len);
rem = msg + part_len;
rem_len = msg_len - part_len;
} else {
memcpy(tmp + 1, msg, msg_len);
memset(tmp + 1 + msg_len, 0xbb, part_len - msg_len);
rem = NULL;
rem_len = 0;
}
crypto_hash_write(ch, tmp + 1, part_len);
crypto_hash_write(ch, rem, rem_len);
const unsigned char *rem;
size_t rem_len;
size_t hash_len = crypto_hash_get_size(ch);
size_t part_len = tmp_len - 2 - hash_len;
if (part_len < msg_len) {
memcpy(tmp + 1, msg, part_len);
rem = msg + part_len;
rem_len = msg_len - part_len;
} else {
memcpy(tmp + 1, msg, msg_len);
memset(tmp + 1 + msg_len, 0xbb, part_len - msg_len);
rem = NULL;
rem_len = 0;
}
crypto_hash_write(ch, tmp + 1, part_len);
crypto_hash_write(ch, rem, rem_len);
va_list vl;
va_start(vl, msg_len);
while (true) {
const struct tlv *add_tlv = va_arg(vl, const struct tlv *);
if (!add_tlv)
break;
va_list vl;
va_start(vl, msg_len);
while (true) {
const struct tlv *add_tlv = va_arg(vl, const struct tlv *);
if (!add_tlv)
break;
crypto_hash_write(ch, add_tlv->value, add_tlv->len);
}
va_end(vl);
crypto_hash_write(ch, add_tlv->value, add_tlv->len);
}
va_end(vl);
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(tmp);
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(tmp);
return NULL;
}
return NULL;
}
memcpy(tmp + 1 + part_len, h, hash_len);
crypto_hash_close(ch);
memcpy(tmp + 1 + part_len, h, hash_len);
crypto_hash_close(ch);
size_t cert_len;
unsigned char *cert = crypto_pk_decrypt(cp, tmp, tmp_len, &cert_len);
free(tmp);
size_t cert_len;
unsigned char *cert = crypto_pk_decrypt(cp, tmp, tmp_len, &cert_len);
free(tmp);
if (!cert)
return NULL;
if (!cert)
return NULL;
struct tlvdb *db = tlvdb_fixed(cert_tag, cert_len, cert);
free(cert);
if (!db)
return NULL;
struct tlvdb *db = tlvdb_fixed(cert_tag, cert_len, cert);
free(cert);
if (!db)
return NULL;
if (rem) {
struct tlvdb *rdb = tlvdb_fixed(rem_tag, rem_len, rem);
if (!rdb) {
tlvdb_free(db);
if (rem) {
struct tlvdb *rdb = tlvdb_fixed(rem_tag, rem_len, rem);
if (!rdb) {
tlvdb_free(db);
return NULL;
}
tlvdb_add(db, rdb);
}
return NULL;
}
tlvdb_add(db, rdb);
}
return db;
return db;
}
static struct tlvdb *emv_pki_sign_key(const struct crypto_pk *cp,
struct emv_pk *ipk,
unsigned char msgtype,
size_t pan_len,
tlv_tag_t cert_tag,
tlv_tag_t exp_tag,
tlv_tag_t rem_tag,
const struct tlv *add_tlv
)
struct emv_pk *ipk,
unsigned char msgtype,
size_t pan_len,
tlv_tag_t cert_tag,
tlv_tag_t exp_tag,
tlv_tag_t rem_tag,
const struct tlv *add_tlv
)
{
unsigned pos = 0;
unsigned char *msg = malloc(1 + pan_len + 2 + 3 + 1 + 1 + 1 + 1 + ipk->mlen);
unsigned pos = 0;
unsigned char *msg = malloc(1 + pan_len + 2 + 3 + 1 + 1 + 1 + 1 + ipk->mlen);
if (!msg)
return NULL;
if (!msg)
return NULL;
msg[pos++] = msgtype;
memcpy(msg + pos, ipk->pan, pan_len); pos += pan_len;
msg[pos++] = (ipk->expire >> 8) & 0xff;
msg[pos++] = (ipk->expire >> 16) & 0xff;
memcpy(msg + pos, ipk->serial, 3); pos += 3;
msg[pos++] = ipk->hash_algo;
msg[pos++] = ipk->pk_algo;
msg[pos++] = ipk->mlen;
msg[pos++] = ipk->elen;
memcpy(msg + pos, ipk->modulus, ipk->mlen);
pos += ipk->mlen;
msg[pos++] = msgtype;
memcpy(msg + pos, ipk->pan, pan_len); pos += pan_len;
msg[pos++] = (ipk->expire >> 8) & 0xff;
msg[pos++] = (ipk->expire >> 16) & 0xff;
memcpy(msg + pos, ipk->serial, 3); pos += 3;
msg[pos++] = ipk->hash_algo;
msg[pos++] = ipk->pk_algo;
msg[pos++] = ipk->mlen;
msg[pos++] = ipk->elen;
memcpy(msg + pos, ipk->modulus, ipk->mlen);
pos += ipk->mlen;
struct tlvdb *exp_db = tlvdb_fixed(exp_tag, ipk->elen, ipk->exp);
if (!exp_db) {
free(msg);
struct tlvdb *exp_db = tlvdb_fixed(exp_tag, ipk->elen, ipk->exp);
if (!exp_db) {
free(msg);
return NULL;
}
return NULL;
}
struct tlvdb *db = emv_pki_sign_message(cp,
cert_tag, rem_tag,
msg, pos,
tlvdb_get(exp_db, exp_tag, NULL),
add_tlv,
NULL);
free(msg);
if (!db)
return NULL;
struct tlvdb *db = emv_pki_sign_message(cp,
cert_tag, rem_tag,
msg, pos,
tlvdb_get(exp_db, exp_tag, NULL),
add_tlv,
NULL);
free(msg);
if (!db)
return NULL;
tlvdb_add(db, exp_db);
tlvdb_add(db, exp_db);
return db;
return db;
}
struct tlvdb *emv_pki_sign_issuer_cert(const struct crypto_pk *cp, struct emv_pk *issuer_pk)
{
return emv_pki_sign_key(cp, issuer_pk, 2, 4, 0x90, 0x9f32, 0x92, NULL);
return emv_pki_sign_key(cp, issuer_pk, 2, 4, 0x90, 0x9f32, 0x92, NULL);
}
struct tlvdb *emv_pki_sign_icc_cert(const struct crypto_pk *cp, struct emv_pk *icc_pk, const struct tlv *sda_tlv)
{
return emv_pki_sign_key(cp, icc_pk, 4, 10, 0x9f46, 0x9f47, 0x9f48, sda_tlv);
return emv_pki_sign_key(cp, icc_pk, 4, 10, 0x9f46, 0x9f47, 0x9f48, sda_tlv);
}
struct tlvdb *emv_pki_sign_icc_pe_cert(const struct crypto_pk *cp, struct emv_pk *icc_pe_pk)
{
return emv_pki_sign_key(cp, icc_pe_pk, 4, 10, 0x9f2d, 0x9f2e, 0x9f2f, NULL);
return emv_pki_sign_key(cp, icc_pe_pk, 4, 10, 0x9f2d, 0x9f2e, 0x9f2f, NULL);
}
struct tlvdb *emv_pki_sign_dac(const struct crypto_pk *cp, const struct tlv *dac_tlv, const struct tlv *sda_tlv)
{
unsigned pos = 0;
unsigned char *msg = malloc(1+1+dac_tlv->len);
unsigned pos = 0;
unsigned char *msg = malloc(1+1+dac_tlv->len);
if (!msg)
return NULL;
if (!msg)
return NULL;
msg[pos++] = 3;
msg[pos++] = HASH_SHA_1;
memcpy(msg+pos, dac_tlv->value, dac_tlv->len);
pos += dac_tlv->len;
msg[pos++] = 3;
msg[pos++] = HASH_SHA_1;
memcpy(msg+pos, dac_tlv->value, dac_tlv->len);
pos += dac_tlv->len;
struct tlvdb *db = emv_pki_sign_message(cp,
0x93, 0,
msg, pos,
sda_tlv,
NULL);
struct tlvdb *db = emv_pki_sign_message(cp,
0x93, 0,
msg, pos,
sda_tlv,
NULL);
free(msg);
free(msg);
return db;
return db;
}
struct tlvdb *emv_pki_sign_idn(const struct crypto_pk *cp, const struct tlv *idn_tlv, const struct tlv *dyn_tlv)
{
unsigned pos = 0;
unsigned char *msg = malloc(1+1+1+1+idn_tlv->len);
unsigned pos = 0;
unsigned char *msg = malloc(1+1+1+1+idn_tlv->len);
if (!msg)
return NULL;
if (!msg)
return NULL;
msg[pos++] = 5;
msg[pos++] = HASH_SHA_1;
msg[pos++] = idn_tlv->len + 1;
msg[pos++] = idn_tlv->len;
memcpy(msg+pos, idn_tlv->value, idn_tlv->len);
pos += idn_tlv->len;
msg[pos++] = 5;
msg[pos++] = HASH_SHA_1;
msg[pos++] = idn_tlv->len + 1;
msg[pos++] = idn_tlv->len;
memcpy(msg+pos, idn_tlv->value, idn_tlv->len);
pos += idn_tlv->len;
struct tlvdb *db = emv_pki_sign_message(cp,
0x9f4b, 0,
msg, pos,
dyn_tlv,
NULL);
struct tlvdb *db = emv_pki_sign_message(cp,
0x9f4b, 0,
msg, pos,
dyn_tlv,
NULL);
free(msg);
free(msg);
return db;
return db;
}

View file

@ -23,8 +23,8 @@
#include <stddef.h>
struct emv_pk *emv_pki_make_ca(const struct crypto_pk *cp,
const unsigned char *rid, unsigned char index,
unsigned int expire, enum crypto_algo_hash hash_algo);
const unsigned char *rid, unsigned char index,
unsigned int expire, enum crypto_algo_hash hash_algo);
struct tlvdb *emv_pki_sign_issuer_cert(const struct crypto_pk *cp, struct emv_pk *issuer_pk);
struct tlvdb *emv_pki_sign_icc_cert(const struct crypto_pk *cp, struct emv_pk *icc_pk, const struct tlv *sda_tlv);
struct tlvdb *emv_pki_sign_icc_pe_cert(const struct crypto_pk *cp, struct emv_pk *icc_pe_pk);

View file

@ -24,152 +24,152 @@
#include "emv_roca.h"
static uint8_t g_primes[ROCA_PRINTS_LENGTH] = {
11, 13, 17, 19, 37, 53, 61, 71, 73, 79, 97, 103, 107, 109, 127, 151, 157
11, 13, 17, 19, 37, 53, 61, 71, 73, 79, 97, 103, 107, 109, 127, 151, 157
};
mbedtls_mpi g_prints[ROCA_PRINTS_LENGTH];
void rocacheck_init(void) {
for (int i = 0; i < ROCA_PRINTS_LENGTH; i++)
mbedtls_mpi_init(&g_prints[i]);
for (int i = 0; i < ROCA_PRINTS_LENGTH; i++)
mbedtls_mpi_init(&g_prints[i]);
mbedtls_mpi_read_string(&g_prints[0], 10, "1026");
mbedtls_mpi_read_string(&g_prints[1], 10, "5658");
mbedtls_mpi_read_string(&g_prints[2], 10, "107286");
mbedtls_mpi_read_string(&g_prints[3], 10, "199410");
mbedtls_mpi_read_string(&g_prints[4], 10, "67109890");
mbedtls_mpi_read_string(&g_prints[5], 10, "5310023542746834");
mbedtls_mpi_read_string(&g_prints[6], 10, "1455791217086302986");
mbedtls_mpi_read_string(&g_prints[7], 10, "20052041432995567486");
mbedtls_mpi_read_string(&g_prints[8], 10, "6041388139249378920330");
mbedtls_mpi_read_string(&g_prints[9], 10, "207530445072488465666");
mbedtls_mpi_read_string(&g_prints[10], 10, "79228162521181866724264247298");
mbedtls_mpi_read_string(&g_prints[11], 10, "1760368345969468176824550810518");
mbedtls_mpi_read_string(&g_prints[12], 10, "50079290986288516948354744811034");
mbedtls_mpi_read_string(&g_prints[13], 10, "473022961816146413042658758988474");
mbedtls_mpi_read_string(&g_prints[14], 10, "144390480366845522447407333004847678774");
mbedtls_mpi_read_string(&g_prints[15], 10, "1800793591454480341970779146165214289059119882");
mbedtls_mpi_read_string(&g_prints[16], 10, "126304807362733370595828809000324029340048915994");
mbedtls_mpi_read_string(&g_prints[0], 10, "1026");
mbedtls_mpi_read_string(&g_prints[1], 10, "5658");
mbedtls_mpi_read_string(&g_prints[2], 10, "107286");
mbedtls_mpi_read_string(&g_prints[3], 10, "199410");
mbedtls_mpi_read_string(&g_prints[4], 10, "67109890");
mbedtls_mpi_read_string(&g_prints[5], 10, "5310023542746834");
mbedtls_mpi_read_string(&g_prints[6], 10, "1455791217086302986");
mbedtls_mpi_read_string(&g_prints[7], 10, "20052041432995567486");
mbedtls_mpi_read_string(&g_prints[8], 10, "6041388139249378920330");
mbedtls_mpi_read_string(&g_prints[9], 10, "207530445072488465666");
mbedtls_mpi_read_string(&g_prints[10], 10, "79228162521181866724264247298");
mbedtls_mpi_read_string(&g_prints[11], 10, "1760368345969468176824550810518");
mbedtls_mpi_read_string(&g_prints[12], 10, "50079290986288516948354744811034");
mbedtls_mpi_read_string(&g_prints[13], 10, "473022961816146413042658758988474");
mbedtls_mpi_read_string(&g_prints[14], 10, "144390480366845522447407333004847678774");
mbedtls_mpi_read_string(&g_prints[15], 10, "1800793591454480341970779146165214289059119882");
mbedtls_mpi_read_string(&g_prints[16], 10, "126304807362733370595828809000324029340048915994");
}
void rocacheck_cleanup(void) {
for (int i = 0; i < ROCA_PRINTS_LENGTH; i++)
mbedtls_mpi_free(&g_prints[i]);
for (int i = 0; i < ROCA_PRINTS_LENGTH; i++)
mbedtls_mpi_free(&g_prints[i]);
}
int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) {
int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) {
for (int i = 0; i < mbedtls_mpi_bitlen(a); i++) {
for (int i = 0; i < mbedtls_mpi_bitlen(a); i++) {
if (mbedtls_mpi_get_bit(a, i) && mbedtls_mpi_get_bit(b, i))
return 0;
}
return 1;
if (mbedtls_mpi_get_bit(a, i) && mbedtls_mpi_get_bit(b, i))
return 0;
}
return 1;
}
mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) {
if (X->n == 1 && X->s > 0) {
return X->p[0];
}
printf("ZERRRRO!!!\n");
return 0;
if (X->n == 1 && X->s > 0) {
return X->p[0];
}
printf("ZERRRRO!!!\n");
return 0;
}
void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) {
char Xchar[400] = {0};
size_t len = 0;
char Xchar[400] = {0};
size_t len = 0;
mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len);
printf("%s[%d] %s\n", msg, len, Xchar);
mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len);
printf("%s[%d] %s\n", msg, len, Xchar);
}
bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) {
mbedtls_mpi t_modulus;
mbedtls_mpi_init(&t_modulus);
mbedtls_mpi t_modulus;
mbedtls_mpi_init(&t_modulus);
bool ret = false;
bool ret = false;
rocacheck_init();
rocacheck_init();
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) );
for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) {
for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) {
mbedtls_mpi t_temp;
mbedtls_mpi t_prime;
mbedtls_mpi g_one;
mbedtls_mpi t_temp;
mbedtls_mpi t_prime;
mbedtls_mpi g_one;
mbedtls_mpi_init(&t_temp);
mbedtls_mpi_init(&t_prime);
mbedtls_mpi_init(&g_one);
mbedtls_mpi_init(&t_temp);
mbedtls_mpi_init(&t_prime);
mbedtls_mpi_init(&g_one);
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) );
if (bitand_is_zero(&g_one, &g_prints[i])) {
if (verbose)
PrintAndLogEx(FAILED, "No fingerprint found.\n");
goto cleanup;
}
if (bitand_is_zero(&g_one, &g_prints[i])) {
if (verbose)
PrintAndLogEx(FAILED, "No fingerprint found.\n");
goto cleanup;
}
mbedtls_mpi_free(&g_one);
mbedtls_mpi_free(&t_temp);
mbedtls_mpi_free(&t_prime);
}
mbedtls_mpi_free(&g_one);
mbedtls_mpi_free(&t_temp);
mbedtls_mpi_free(&t_prime);
}
ret = true;
if (verbose)
PrintAndLogEx(SUCCESS, "Fingerprint found!\n");
ret = true;
if (verbose)
PrintAndLogEx(SUCCESS, "Fingerprint found!\n");
cleanup:
mbedtls_mpi_free(&t_modulus);
mbedtls_mpi_free(&t_modulus);
rocacheck_cleanup();
return ret;
rocacheck_cleanup();
return ret;
}
int roca_self_test(void) {
int ret = 0;
int ret = 0;
PrintAndLogEx(INFO, "ROCA check vulnerability tests" );
PrintAndLogEx(INFO, "ROCA check vulnerability tests" );
// positive
uint8_t keyp[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\
"\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\
"\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\
"\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7";
// positive
uint8_t keyp[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\
"\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\
"\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\
"\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7";
if (emv_rocacheck(keyp, 64, false)) {
PrintAndLogEx(SUCCESS, "Weak modulus [ %s]", _GREEN_(PASS) );
}
else {
ret++;
PrintAndLogEx(FAILED, "Weak modulus [ %s]", _RED_(FAIL) );
}
if (emv_rocacheck(keyp, 64, false)) {
PrintAndLogEx(SUCCESS, "Weak modulus [ %s]", _GREEN_(PASS) );
}
else {
ret++;
PrintAndLogEx(FAILED, "Weak modulus [ %s]", _RED_(FAIL) );
}
// negative
uint8_t keyn[] = "\x84\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\
"\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\
"\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\
"\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7";
// negative
uint8_t keyn[] = "\x84\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\
"\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\
"\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\
"\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7";
if (emv_rocacheck(keyn, 64, false)) {
ret++;
PrintAndLogEx(FAILED, "Strong modulus [ %s]", _RED_(FAIL) );
} else {
PrintAndLogEx(SUCCESS, "Strong modulus [ %s]", _GREEN_(PASS) );
}
if (emv_rocacheck(keyn, 64, false)) {
ret++;
PrintAndLogEx(FAILED, "Strong modulus [ %s]", _RED_(FAIL) );
} else {
PrintAndLogEx(SUCCESS, "Strong modulus [ %s]", _GREEN_(PASS) );
}
return ret;
return ret;
}

View file

@ -29,7 +29,7 @@
#include "mbedtls/bignum.h"
#include "util.h"
#define ROCA_PRINTS_LENGTH 17
#define ROCA_PRINTS_LENGTH 17
extern bool emv_rocacheck( const unsigned char *buf, size_t buflen, bool verbose );
extern int roca_self_test( void );

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -33,35 +33,35 @@
#define APDU_AID_LEN 50
typedef enum {
ECC_CONTACTLESS,
ECC_CONTACT
ECC_CONTACTLESS,
ECC_CONTACT
} EMVCommandChannel;
enum TransactionType {
TT_MSD,
TT_VSDC, // contact only. not standart for contactless
TT_QVSDCMCHIP,
TT_CDA,
TT_MSD,
TT_VSDC, // contact only. not standart for contactless
TT_QVSDCMCHIP,
TT_CDA,
};
extern char *TransactionTypeStr[];
typedef struct {
uint8_t CLA;
uint8_t INS;
uint8_t P1;
uint8_t P2;
uint8_t Lc;
uint8_t *data;
uint8_t CLA;
uint8_t INS;
uint8_t P1;
uint8_t P2;
uint8_t Lc;
uint8_t *data;
} sAPDU;
enum CardPSVendor {
CV_NA,
CV_VISA,
CV_MASTERCARD,
CV_AMERICANEXPRESS,
CV_JCB,
CV_CB,
CV_OTHER,
CV_NA,
CV_VISA,
CV_MASTERCARD,
CV_AMERICANEXPRESS,
CV_JCB,
CV_CB,
CV_OTHER,
};
extern enum CardPSVendor GetCardPSVendor(uint8_t * AID, size_t AIDlen);

View file

@ -61,342 +61,342 @@ static const ApplicationDataElm ApplicationData[] = {
int ApplicationDataLen = sizeof(ApplicationData) / sizeof(ApplicationDataElm);
char* GetApplicationDataName(tlv_tag_t tag) {
for (int i = 0; i < ApplicationDataLen; i++)
if (ApplicationData[i].Tag == tag)
return ApplicationData[i].Name;
for (int i = 0; i < ApplicationDataLen; i++)
if (ApplicationData[i].Tag == tag)
return ApplicationData[i].Name;
return NULL;
return NULL;
}
int JsonSaveJsonObject(json_t *root, char *path, json_t *value) {
json_error_t error;
json_error_t error;
if (strlen(path) < 1)
return 1;
if (strlen(path) < 1)
return 1;
if (path[0] == '$') {
if (json_path_set(root, path, value, 0, &error)) {
PrintAndLog("ERROR: can't set json path: ", error.text);
return 2;
} else {
return 0;
}
} else {
return json_object_set_new(root, path, value);
}
if (path[0] == '$') {
if (json_path_set(root, path, value, 0, &error)) {
PrintAndLog("ERROR: can't set json path: ", error.text);
return 2;
} else {
return 0;
}
} else {
return json_object_set_new(root, path, value);
}
}
int JsonSaveInt(json_t *root, char *path, int value) {
return JsonSaveJsonObject(root, path, json_integer(value));
return JsonSaveJsonObject(root, path, json_integer(value));
}
int JsonSaveStr(json_t *root, char *path, char *value) {
return JsonSaveJsonObject(root, path, json_string(value));
return JsonSaveJsonObject(root, path, json_string(value));
};
int JsonSaveBufAsHexCompact(json_t *elm, char *path, uint8_t *data, size_t datalen) {
char * msg = sprint_hex_inrow(data, datalen);
if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ')
msg[strlen(msg) - 1] = '\0';
char * msg = sprint_hex_inrow(data, datalen);
if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ')
msg[strlen(msg) - 1] = '\0';
return JsonSaveStr(elm, path, msg);
return JsonSaveStr(elm, path, msg);
}
int JsonSaveBufAsHex(json_t *elm, char *path, uint8_t *data, size_t datalen) {
char * msg = sprint_hex(data, datalen);
if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ')
msg[strlen(msg) - 1] = '\0';
char * msg = sprint_hex(data, datalen);
if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ')
msg[strlen(msg) - 1] = '\0';
return JsonSaveStr(elm, path, msg);
return JsonSaveStr(elm, path, msg);
}
int JsonSaveHex(json_t *elm, char *path, uint64_t data, int datalen) {
uint8_t bdata[8] = {0};
int len = 0;
if (!datalen) {
for (uint64_t u = 0xffffffffffffffff; u; u = u << 8) {
if (!(data & u)) {
break;
}
len++;
}
if (!len)
len = 1;
} else {
len = datalen;
}
num_to_bytes(data, len, bdata);
uint8_t bdata[8] = {0};
int len = 0;
if (!datalen) {
for (uint64_t u = 0xffffffffffffffff; u; u = u << 8) {
if (!(data & u)) {
break;
}
len++;
}
if (!len)
len = 1;
} else {
len = datalen;
}
num_to_bytes(data, len, bdata);
return JsonSaveBufAsHex(elm, path, bdata, len);
return JsonSaveBufAsHex(elm, path, bdata, len);
}
int JsonSaveTLVValue(json_t *root, char *path, struct tlvdb *tlvdbelm) {
const struct tlv *tlvelm = tlvdb_get_tlv(tlvdbelm);
if (tlvelm)
return JsonSaveBufAsHex(root, path, (uint8_t *)tlvelm->value, tlvelm->len);
else
return 1;
const struct tlv *tlvelm = tlvdb_get_tlv(tlvdbelm);
if (tlvelm)
return JsonSaveBufAsHex(root, path, (uint8_t *)tlvelm->value, tlvelm->len);
else
return 1;
}
int JsonSaveTLVElm(json_t *elm, char *path, struct tlv *tlvelm, bool saveName, bool saveValue, bool saveAppDataLink) {
json_error_t error;
json_error_t error;
if (strlen(path) < 1 || !tlvelm)
return 1;
if (strlen(path) < 1 || !tlvelm)
return 1;
if (path[0] == '$') {
if (path[0] == '$') {
json_t *obj = json_path_get(elm, path);
if (!obj) {
obj = json_object();
json_t *obj = json_path_get(elm, path);
if (!obj) {
obj = json_object();
if (json_is_array(elm)) {
if (json_array_append_new(elm, obj)) {
PrintAndLog("ERROR: can't append array: %s", path);
return 2;
}
} else {
if (json_path_set(elm, path, obj, 0, &error)) {
PrintAndLog("ERROR: can't set json path: ", error.text);
return 2;
}
}
}
if (json_is_array(elm)) {
if (json_array_append_new(elm, obj)) {
PrintAndLog("ERROR: can't append array: %s", path);
return 2;
}
} else {
if (json_path_set(elm, path, obj, 0, &error)) {
PrintAndLog("ERROR: can't set json path: ", error.text);
return 2;
}
}
}
if (saveAppDataLink) {
char * AppDataName = GetApplicationDataName(tlvelm->tag);
if (AppDataName)
JsonSaveStr(obj, "appdata", AppDataName);
} else {
char * name = emv_get_tag_name(tlvelm);
if (saveName && name && strlen(name) > 0 && strncmp(name, "Unknown", 7))
JsonSaveStr(obj, "name", emv_get_tag_name(tlvelm));
JsonSaveHex(obj, "tag", tlvelm->tag, 0);
if (saveValue) {
JsonSaveHex(obj, "length", tlvelm->len, 0);
JsonSaveBufAsHex(obj, "value", (uint8_t *)tlvelm->value, tlvelm->len);
};
}
}
if (saveAppDataLink) {
char * AppDataName = GetApplicationDataName(tlvelm->tag);
if (AppDataName)
JsonSaveStr(obj, "appdata", AppDataName);
} else {
char * name = emv_get_tag_name(tlvelm);
if (saveName && name && strlen(name) > 0 && strncmp(name, "Unknown", 7))
JsonSaveStr(obj, "name", emv_get_tag_name(tlvelm));
JsonSaveHex(obj, "tag", tlvelm->tag, 0);
if (saveValue) {
JsonSaveHex(obj, "length", tlvelm->len, 0);
JsonSaveBufAsHex(obj, "value", (uint8_t *)tlvelm->value, tlvelm->len);
};
}
}
return 0;
return 0;
}
int JsonSaveTLVTreeElm(json_t *elm, char *path, struct tlvdb *tlvdbelm, bool saveName, bool saveValue, bool saveAppDataLink) {
return JsonSaveTLVElm(elm, path, (struct tlv *)tlvdb_get_tlv(tlvdbelm), saveName, saveValue, saveAppDataLink);
return JsonSaveTLVElm(elm, path, (struct tlv *)tlvdb_get_tlv(tlvdbelm), saveName, saveValue, saveAppDataLink);
}
int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbelm) {
struct tlvdb *tlvp = tlvdbelm;
while (tlvp) {
const struct tlv * tlvpelm = tlvdb_get_tlv(tlvp);
char * AppDataName = NULL;
if (tlvpelm)
AppDataName = GetApplicationDataName(tlvpelm->tag);
struct tlvdb *tlvp = tlvdbelm;
while (tlvp) {
const struct tlv * tlvpelm = tlvdb_get_tlv(tlvp);
char * AppDataName = NULL;
if (tlvpelm)
AppDataName = GetApplicationDataName(tlvpelm->tag);
if (AppDataName) {
char appdatalink[200] = {0};
sprintf(appdatalink, "$.ApplicationData.%s", AppDataName);
JsonSaveBufAsHex(root, appdatalink, (uint8_t *)tlvpelm->value, tlvpelm->len);
}
if (AppDataName) {
char appdatalink[200] = {0};
sprintf(appdatalink, "$.ApplicationData.%s", AppDataName);
JsonSaveBufAsHex(root, appdatalink, (uint8_t *)tlvpelm->value, tlvpelm->len);
}
json_t *pelm = json_path_get(elm, path);
if (pelm && json_is_array(pelm)) {
json_t *appendelm = json_object();
json_array_append_new(pelm, appendelm);
JsonSaveTLVTreeElm(appendelm, "$", tlvp, !AppDataName, !tlvdb_elm_get_children(tlvp), AppDataName);
pelm = appendelm;
} else {
JsonSaveTLVTreeElm(elm, path, tlvp, !AppDataName, !tlvdb_elm_get_children(tlvp), AppDataName);
pelm = json_path_get(elm, path);
}
json_t *pelm = json_path_get(elm, path);
if (pelm && json_is_array(pelm)) {
json_t *appendelm = json_object();
json_array_append_new(pelm, appendelm);
JsonSaveTLVTreeElm(appendelm, "$", tlvp, !AppDataName, !tlvdb_elm_get_children(tlvp), AppDataName);
pelm = appendelm;
} else {
JsonSaveTLVTreeElm(elm, path, tlvp, !AppDataName, !tlvdb_elm_get_children(tlvp), AppDataName);
pelm = json_path_get(elm, path);
}
if (tlvdb_elm_get_children(tlvp)) {
// get path element
if(!pelm)
return 1;
if (tlvdb_elm_get_children(tlvp)) {
// get path element
if(!pelm)
return 1;
// check childs element and add it if not found
json_t *chjson = json_path_get(pelm, "$.Childs");
if (!chjson) {
json_object_set_new(pelm, "Childs", json_array());
// check childs element and add it if not found
json_t *chjson = json_path_get(pelm, "$.Childs");
if (!chjson) {
json_object_set_new(pelm, "Childs", json_array());
chjson = json_path_get(pelm, "$.Childs");
}
chjson = json_path_get(pelm, "$.Childs");
}
// check
if (!json_is_array(chjson)) {
PrintAndLog("E->Internal logic error. `$.Childs` is not an array.");
break;
}
// check
if (!json_is_array(chjson)) {
PrintAndLog("E->Internal logic error. `$.Childs` is not an array.");
break;
}
// Recursion
JsonSaveTLVTree(root, chjson, "$", tlvdb_elm_get_children(tlvp));
}
// Recursion
JsonSaveTLVTree(root, chjson, "$", tlvdb_elm_get_children(tlvp));
}
tlvp = tlvdb_elm_get_next(tlvp);
}
return 0;
tlvp = tlvdb_elm_get_next(tlvp);
}
return 0;
}
bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, size_t maxbufferlen, size_t *bufferlen) {
int buflen = 0;
int buflen = 0;
switch (param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
case 1:
PrintAndLog("%s Invalid HEX value.", errormsg);
return false;
case 2:
PrintAndLog("%s Hex value too large.", errormsg);
return false;
case 3:
PrintAndLog("%s Hex value must have even number of digits.", errormsg);
return false;
}
switch (param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
case 1:
PrintAndLog("%s Invalid HEX value.", errormsg);
return false;
case 2:
PrintAndLog("%s Hex value too large.", errormsg);
return false;
case 3:
PrintAndLog("%s Hex value must have even number of digits.", errormsg);
return false;
}
if (buflen > maxbufferlen) {
PrintAndLog("%s HEX length (%d) more than %d", errormsg, (bufferlen) ? *bufferlen : -1, maxbufferlen);
return false;
}
if (buflen > maxbufferlen) {
PrintAndLog("%s HEX length (%d) more than %d", errormsg, (bufferlen) ? *bufferlen : -1, maxbufferlen);
return false;
}
if ( bufferlen )
*bufferlen = buflen;
if ( bufferlen )
*bufferlen = buflen;
return true;
return true;
}
int JsonLoadStr(json_t *root, char *path, char *value) {
if (!value)
return 1;
if (!value)
return 1;
json_t *jelm = json_path_get((const json_t *)root, path);
if (!jelm || !json_is_string(jelm))
return 2;
json_t *jelm = json_path_get((const json_t *)root, path);
if (!jelm || !json_is_string(jelm))
return 2;
const char * strval = json_string_value(jelm);
if (!strval)
return 1;
const char * strval = json_string_value(jelm);
if (!strval)
return 1;
memcpy(value, strval, strlen(strval));
memcpy(value, strval, strlen(strval));
return 0;
return 0;
}
int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen) {
if (datalen)
*datalen = 0;
if (datalen)
*datalen = 0;
json_t *jelm = json_path_get((const json_t *)elm, path);
if (!jelm || !json_is_string(jelm))
return 1;
json_t *jelm = json_path_get((const json_t *)elm, path);
if (!jelm || !json_is_string(jelm))
return 1;
if (!HexToBuffer("ERROR load", json_string_value(jelm), data, maxbufferlen, datalen))
return 2;
if (!HexToBuffer("ERROR load", json_string_value(jelm), data, maxbufferlen, datalen))
return 2;
return 0;
return 0;
};
bool ParamLoadFromJson(struct tlvdb *tlv) {
json_t *root;
json_error_t error;
json_t *root;
json_error_t error;
if (!tlv) {
PrintAndLog("ERROR load params: tlv tree is NULL.");
return false;
}
if (!tlv) {
PrintAndLog("ERROR load params: tlv tree is NULL.");
return false;
}
// current path + file name
const char *relfname = "emv/defparams.json";
char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1];
strcpy(fname, get_my_executable_directory());
strcat(fname, relfname);
// current path + file name
const char *relfname = "emv/defparams.json";
char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1];
strcpy(fname, get_my_executable_directory());
strcat(fname, relfname);
root = json_load_file(fname, 0, &error);
if (!root) {
PrintAndLog("Load params: json error on line %d: %s", error.line, error.text);
return false;
}
root = json_load_file(fname, 0, &error);
if (!root) {
PrintAndLog("Load params: json error on line %d: %s", error.line, error.text);
return false;
}
if (!json_is_array(root)) {
PrintAndLog("Load params: Invalid json format. root must be array.");
return false;
}
if (!json_is_array(root)) {
PrintAndLog("Load params: Invalid json format. root must be array.");
return false;
}
PrintAndLog("Load params: json(%d) OK", json_array_size(root));
PrintAndLog("Load params: json(%d) OK", json_array_size(root));
for(int i = 0; i < json_array_size(root); i++) {
json_t *data, *jtag, *jlength, *jvalue;
for(int i = 0; i < json_array_size(root); i++) {
json_t *data, *jtag, *jlength, *jvalue;
data = json_array_get(root, i);
if(!json_is_object(data))
{
PrintAndLog("Load params: data [%d] is not an object", i + 1);
json_decref(root);
return false;
}
data = json_array_get(root, i);
if(!json_is_object(data))
{
PrintAndLog("Load params: data [%d] is not an object", i + 1);
json_decref(root);
return false;
}
jtag = json_object_get(data, "tag");
if(!json_is_string(jtag))
{
PrintAndLog("Load params: data [%d] tag is not a string", i + 1);
json_decref(root);
return false;
}
const char *tlvTag = json_string_value(jtag);
jtag = json_object_get(data, "tag");
if(!json_is_string(jtag))
{
PrintAndLog("Load params: data [%d] tag is not a string", i + 1);
json_decref(root);
return false;
}
const char *tlvTag = json_string_value(jtag);
jvalue = json_object_get(data, "value");
if(!json_is_string(jvalue))
{
PrintAndLog("Load params: data [%d] value is not a string", i + 1);
json_decref(root);
return false;
}
const char *tlvValue = json_string_value(jvalue);
jvalue = json_object_get(data, "value");
if(!json_is_string(jvalue))
{
PrintAndLog("Load params: data [%d] value is not a string", i + 1);
json_decref(root);
return false;
}
const char *tlvValue = json_string_value(jvalue);
jlength = json_object_get(data, "length");
if(!json_is_number(jlength))
{
PrintAndLog("Load params: data [%d] length is not a number", i + 1);
json_decref(root);
return false;
}
jlength = json_object_get(data, "length");
if(!json_is_number(jlength))
{
PrintAndLog("Load params: data [%d] length is not a number", i + 1);
json_decref(root);
return false;
}
int tlvLength = json_integer_value(jlength);
if (tlvLength > 250) {
PrintAndLog("Load params: data [%d] length more than 250", i + 1);
json_decref(root);
return false;
}
int tlvLength = json_integer_value(jlength);
if (tlvLength > 250) {
PrintAndLog("Load params: data [%d] length more than 250", i + 1);
json_decref(root);
return false;
}
PrintAndLog("TLV param: %s[%d]=%s", tlvTag, tlvLength, tlvValue);
uint8_t buf[251] = {0};
size_t buflen = 0;
PrintAndLog("TLV param: %s[%d]=%s", tlvTag, tlvLength, tlvValue);
uint8_t buf[251] = {0};
size_t buflen = 0;
if (!HexToBuffer("TLV Error type:", tlvTag, buf, 4, &buflen)) {
json_decref(root);
return false;
}
tlv_tag_t tag = 0;
for (int i = 0; i < buflen; i++) {
tag = (tag << 8) | buf[i];
}
if (!HexToBuffer("TLV Error type:", tlvTag, buf, 4, &buflen)) {
json_decref(root);
return false;
}
tlv_tag_t tag = 0;
for (int i = 0; i < buflen; i++) {
tag = (tag << 8) | buf[i];
}
if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) {
json_decref(root);
return false;
}
if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) {
json_decref(root);
return false;
}
if (buflen != tlvLength) {
PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength);
json_decref(root);
return false;
}
if (buflen != tlvLength) {
PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength);
json_decref(root);
return false;
}
tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf);
}
tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf);
}
json_decref(root);
json_decref(root);
return true;
return true;
}

View file

@ -14,8 +14,8 @@
#include "tlv.h"
typedef struct {
tlv_tag_t Tag;
char *Name;
tlv_tag_t Tag;
char *Name;
} ApplicationDataElm;
extern char* GetApplicationDataName(tlv_tag_t tag);

View file

@ -28,415 +28,415 @@
#include <stdlib.h>
struct emv_pk c_mchip_05 = {
.rid = { 0xa0, 0x00, 0x00, 0x00, 0x04, },
.index = 5,
.hash_algo = HASH_SHA_1,
.pk_algo = PK_RSA,
.hash = {
0xeb, 0xfa, 0x0d, 0x5d,
0x06, 0xd8, 0xce, 0x70,
0x2d, 0xa3, 0xea, 0xe8,
0x90, 0x70, 0x1d, 0x45,
0xe2, 0x74, 0xc8, 0x45, },
.exp = { 0x03, },
.elen = 1,
.mlen = 1408 / 8,
.modulus = (unsigned char[]){
0xb8, 0x04, 0x8a, 0xbc, 0x30, 0xc9, 0x0d, 0x97, 0x63, 0x36, 0x54, 0x3e, 0x3f, 0xd7, 0x09, 0x1c,
0x8f, 0xe4, 0x80, 0x0d, 0xf8, 0x20, 0xed, 0x55, 0xe7, 0xe9, 0x48, 0x13, 0xed, 0x00, 0x55, 0x5b,
0x57, 0x3f, 0xec, 0xa3, 0xd8, 0x4a, 0xf6, 0x13, 0x1a, 0x65, 0x1d, 0x66, 0xcf, 0xf4, 0x28, 0x4f,
0xb1, 0x3b, 0x63, 0x5e, 0xdd, 0x0e, 0xe4, 0x01, 0x76, 0xd8, 0xbf, 0x04, 0xb7, 0xfd, 0x1c, 0x7b,
0xac, 0xf9, 0xac, 0x73, 0x27, 0xdf, 0xaa, 0x8a, 0xa7, 0x2d, 0x10, 0xdb, 0x3b, 0x8e, 0x70, 0xb2,
0xdd, 0xd8, 0x11, 0xcb, 0x41, 0x96, 0x52, 0x5e, 0xa3, 0x86, 0xac, 0xc3, 0x3c, 0x0d, 0x9d, 0x45,
0x75, 0x91, 0x64, 0x69, 0xc4, 0xe4, 0xf5, 0x3e, 0x8e, 0x1c, 0x91, 0x2c, 0xc6, 0x18, 0xcb, 0x22,
0xdd, 0xe7, 0xc3, 0x56, 0x8e, 0x90, 0x02, 0x2e, 0x6b, 0xba, 0x77, 0x02, 0x02, 0xe4, 0x52, 0x2a,
0x2d, 0xd6, 0x23, 0xd1, 0x80, 0xe2, 0x15, 0xbd, 0x1d, 0x15, 0x07, 0xfe, 0x3d, 0xc9, 0x0c, 0xa3,
0x10, 0xd2, 0x7b, 0x3e, 0xfc, 0xcd, 0x8f, 0x83, 0xde, 0x30, 0x52, 0xca, 0xd1, 0xe4, 0x89, 0x38,
0xc6, 0x8d, 0x09, 0x5a, 0xac, 0x91, 0xb5, 0xf3, 0x7e, 0x28, 0xbb, 0x49, 0xec, 0x7e, 0xd5, 0x97,
},
.rid = { 0xa0, 0x00, 0x00, 0x00, 0x04, },
.index = 5,
.hash_algo = HASH_SHA_1,
.pk_algo = PK_RSA,
.hash = {
0xeb, 0xfa, 0x0d, 0x5d,
0x06, 0xd8, 0xce, 0x70,
0x2d, 0xa3, 0xea, 0xe8,
0x90, 0x70, 0x1d, 0x45,
0xe2, 0x74, 0xc8, 0x45, },
.exp = { 0x03, },
.elen = 1,
.mlen = 1408 / 8,
.modulus = (unsigned char[]){
0xb8, 0x04, 0x8a, 0xbc, 0x30, 0xc9, 0x0d, 0x97, 0x63, 0x36, 0x54, 0x3e, 0x3f, 0xd7, 0x09, 0x1c,
0x8f, 0xe4, 0x80, 0x0d, 0xf8, 0x20, 0xed, 0x55, 0xe7, 0xe9, 0x48, 0x13, 0xed, 0x00, 0x55, 0x5b,
0x57, 0x3f, 0xec, 0xa3, 0xd8, 0x4a, 0xf6, 0x13, 0x1a, 0x65, 0x1d, 0x66, 0xcf, 0xf4, 0x28, 0x4f,
0xb1, 0x3b, 0x63, 0x5e, 0xdd, 0x0e, 0xe4, 0x01, 0x76, 0xd8, 0xbf, 0x04, 0xb7, 0xfd, 0x1c, 0x7b,
0xac, 0xf9, 0xac, 0x73, 0x27, 0xdf, 0xaa, 0x8a, 0xa7, 0x2d, 0x10, 0xdb, 0x3b, 0x8e, 0x70, 0xb2,
0xdd, 0xd8, 0x11, 0xcb, 0x41, 0x96, 0x52, 0x5e, 0xa3, 0x86, 0xac, 0xc3, 0x3c, 0x0d, 0x9d, 0x45,
0x75, 0x91, 0x64, 0x69, 0xc4, 0xe4, 0xf5, 0x3e, 0x8e, 0x1c, 0x91, 0x2c, 0xc6, 0x18, 0xcb, 0x22,
0xdd, 0xe7, 0xc3, 0x56, 0x8e, 0x90, 0x02, 0x2e, 0x6b, 0xba, 0x77, 0x02, 0x02, 0xe4, 0x52, 0x2a,
0x2d, 0xd6, 0x23, 0xd1, 0x80, 0xe2, 0x15, 0xbd, 0x1d, 0x15, 0x07, 0xfe, 0x3d, 0xc9, 0x0c, 0xa3,
0x10, 0xd2, 0x7b, 0x3e, 0xfc, 0xcd, 0x8f, 0x83, 0xde, 0x30, 0x52, 0xca, 0xd1, 0xe4, 0x89, 0x38,
0xc6, 0x8d, 0x09, 0x5a, 0xac, 0x91, 0xb5, 0xf3, 0x7e, 0x28, 0xbb, 0x49, 0xec, 0x7e, 0xd5, 0x97,
},
};
const unsigned char c_issuer_cert[] = {
0x17, 0x14, 0x28, 0x4f, 0x76, 0x3b, 0x85, 0x86, 0xee, 0x6d, 0x31, 0x99, 0x51, 0xf7, 0xe6, 0x3f,
0xa2, 0x50, 0x76, 0xe5, 0x0d, 0xc9, 0xd3, 0x20, 0x0b, 0xa9, 0x98, 0xd3, 0xa0, 0x52, 0xad, 0xba,
0x9a, 0xb6, 0x9a, 0xc6, 0xad, 0x6a, 0xdd, 0x3c, 0xe0, 0x9f, 0x02, 0x78, 0xf4, 0x07, 0x4e, 0xc4,
0xee, 0x9b, 0x1d, 0x22, 0x68, 0xa3, 0xe9, 0x53, 0x57, 0x5e, 0x45, 0x4e, 0x50, 0xcd, 0x86, 0x0b,
0xf4, 0x24, 0xc5, 0x1c, 0x59, 0x77, 0x12, 0xd2, 0xaa, 0x05, 0x70, 0x89, 0xdd, 0x86, 0x73, 0xe5,
0x1b, 0x1e, 0x1d, 0x71, 0x88, 0x03, 0x48, 0x92, 0x07, 0x7a, 0xc1, 0x8a, 0x6a, 0xe2, 0x34, 0x88,
0xbe, 0xa9, 0xdf, 0x3b, 0x1a, 0x83, 0xf2, 0xc0, 0x80, 0x0c, 0xd7, 0xc5, 0xcd, 0xf2, 0xfd, 0xe0,
0x49, 0x6f, 0x7b, 0xc3, 0x9f, 0xb4, 0xbf, 0x36, 0x32, 0x99, 0xbf, 0xa6, 0x37, 0xb2, 0xec, 0x33,
0xc5, 0x07, 0xe3, 0x68, 0x21, 0xee, 0xc2, 0x07, 0x5f, 0x0e, 0x42, 0x0d, 0x38, 0xa1, 0xc9, 0xf3,
0x12, 0x72, 0x61, 0xba, 0x31, 0x6c, 0x98, 0x76, 0x74, 0xfa, 0xdb, 0x20, 0xea, 0x7f, 0xeb, 0x75,
0xee, 0x45, 0x5d, 0x12, 0x14, 0x6e, 0xa6, 0xf0, 0x2e, 0x8b, 0x01, 0xec, 0x2f, 0xa7, 0xa1, 0x15,
0x17, 0x14, 0x28, 0x4f, 0x76, 0x3b, 0x85, 0x86, 0xee, 0x6d, 0x31, 0x99, 0x51, 0xf7, 0xe6, 0x3f,
0xa2, 0x50, 0x76, 0xe5, 0x0d, 0xc9, 0xd3, 0x20, 0x0b, 0xa9, 0x98, 0xd3, 0xa0, 0x52, 0xad, 0xba,
0x9a, 0xb6, 0x9a, 0xc6, 0xad, 0x6a, 0xdd, 0x3c, 0xe0, 0x9f, 0x02, 0x78, 0xf4, 0x07, 0x4e, 0xc4,
0xee, 0x9b, 0x1d, 0x22, 0x68, 0xa3, 0xe9, 0x53, 0x57, 0x5e, 0x45, 0x4e, 0x50, 0xcd, 0x86, 0x0b,
0xf4, 0x24, 0xc5, 0x1c, 0x59, 0x77, 0x12, 0xd2, 0xaa, 0x05, 0x70, 0x89, 0xdd, 0x86, 0x73, 0xe5,
0x1b, 0x1e, 0x1d, 0x71, 0x88, 0x03, 0x48, 0x92, 0x07, 0x7a, 0xc1, 0x8a, 0x6a, 0xe2, 0x34, 0x88,
0xbe, 0xa9, 0xdf, 0x3b, 0x1a, 0x83, 0xf2, 0xc0, 0x80, 0x0c, 0xd7, 0xc5, 0xcd, 0xf2, 0xfd, 0xe0,
0x49, 0x6f, 0x7b, 0xc3, 0x9f, 0xb4, 0xbf, 0x36, 0x32, 0x99, 0xbf, 0xa6, 0x37, 0xb2, 0xec, 0x33,
0xc5, 0x07, 0xe3, 0x68, 0x21, 0xee, 0xc2, 0x07, 0x5f, 0x0e, 0x42, 0x0d, 0x38, 0xa1, 0xc9, 0xf3,
0x12, 0x72, 0x61, 0xba, 0x31, 0x6c, 0x98, 0x76, 0x74, 0xfa, 0xdb, 0x20, 0xea, 0x7f, 0xeb, 0x75,
0xee, 0x45, 0x5d, 0x12, 0x14, 0x6e, 0xa6, 0xf0, 0x2e, 0x8b, 0x01, 0xec, 0x2f, 0xa7, 0xa1, 0x15,
};
const unsigned char c_issuer_rem[] = {
0x6e, 0x63, 0xb7, 0xbc, 0x70, 0xab, 0xdd, 0x09, 0x34, 0x1b, 0x34, 0xc0, 0x32, 0x86, 0xba, 0x9b,
0xd8, 0x3b, 0xa7, 0x93, 0x6c, 0x5b, 0x77, 0x98, 0xfb, 0x22, 0xc5, 0xe5, 0x3f, 0xf2, 0x40, 0xa2,
0x6d, 0xbd, 0x64, 0x15,
0x6e, 0x63, 0xb7, 0xbc, 0x70, 0xab, 0xdd, 0x09, 0x34, 0x1b, 0x34, 0xc0, 0x32, 0x86, 0xba, 0x9b,
0xd8, 0x3b, 0xa7, 0x93, 0x6c, 0x5b, 0x77, 0x98, 0xfb, 0x22, 0xc5, 0xe5, 0x3f, 0xf2, 0x40, 0xa2,
0x6d, 0xbd, 0x64, 0x15,
};
const unsigned char c_issuer_exp[] = {
0x03,
0x03,
};
const unsigned char c_icc_cert[] = {
0xa4, 0x2f, 0xbe, 0xb1, 0x56, 0xb9, 0x8d, 0xcb, 0x05, 0x54, 0xda, 0x06, 0x2a, 0xdc, 0xa5, 0x30,
0x9a, 0x91, 0xf0, 0x4f, 0xa2, 0xc7, 0xbd, 0x71, 0x02, 0xa8, 0xd7, 0x3f, 0x16, 0xa3, 0xcf, 0xad,
0xe8, 0xaa, 0xdf, 0x4f, 0x3f, 0xe2, 0xa2, 0x12, 0x5c, 0xcd, 0xd7, 0x7c, 0x6b, 0x9f, 0x78, 0xb5,
0xb4, 0x37, 0x1c, 0xe0, 0x80, 0x57, 0x25, 0xb0, 0xf9, 0xc0, 0x27, 0xaf, 0x14, 0x7d, 0x91, 0xe1,
0xff, 0xdb, 0x20, 0x1e, 0x9c, 0x17, 0x0c, 0xe7, 0x77, 0x05, 0x3a, 0x17, 0x2a, 0xd5, 0x26, 0xdc,
0xaf, 0xd3, 0x38, 0x95, 0xe1, 0xa9, 0x47, 0x30, 0x5c, 0x5b, 0x16, 0x7f, 0x2e, 0x7c, 0x6f, 0x99,
0x15, 0x81, 0xa6, 0x52, 0xee, 0x47, 0x31, 0x54, 0x76, 0x0c, 0x2e, 0xd7, 0x74, 0x21, 0x4e, 0x50,
0xdf, 0xec, 0xdd, 0x4c, 0xf2, 0x94, 0xc9, 0x74, 0xb8, 0x9e, 0xbc, 0xa2, 0x5b, 0x5a, 0xb3, 0xc0,
0xbe, 0xb5, 0x0d, 0xfa, 0xf7, 0x82, 0xaf, 0xde, 0x14, 0x33, 0xd9, 0x0c, 0xa2, 0xa8, 0x9d, 0x65,
0x1e, 0x75, 0xd6, 0x7e, 0xbc, 0x7c, 0x3e, 0x36, 0xf5, 0xa1, 0x65, 0xee, 0x61, 0x32, 0x61, 0x29,
0x39, 0xc1, 0xec, 0xd3, 0x99, 0xe4, 0x60, 0x74, 0xb9, 0x96, 0xd9, 0x3a, 0x88, 0xe0, 0x1e, 0x0a,
0xa4, 0x2f, 0xbe, 0xb1, 0x56, 0xb9, 0x8d, 0xcb, 0x05, 0x54, 0xda, 0x06, 0x2a, 0xdc, 0xa5, 0x30,
0x9a, 0x91, 0xf0, 0x4f, 0xa2, 0xc7, 0xbd, 0x71, 0x02, 0xa8, 0xd7, 0x3f, 0x16, 0xa3, 0xcf, 0xad,
0xe8, 0xaa, 0xdf, 0x4f, 0x3f, 0xe2, 0xa2, 0x12, 0x5c, 0xcd, 0xd7, 0x7c, 0x6b, 0x9f, 0x78, 0xb5,
0xb4, 0x37, 0x1c, 0xe0, 0x80, 0x57, 0x25, 0xb0, 0xf9, 0xc0, 0x27, 0xaf, 0x14, 0x7d, 0x91, 0xe1,
0xff, 0xdb, 0x20, 0x1e, 0x9c, 0x17, 0x0c, 0xe7, 0x77, 0x05, 0x3a, 0x17, 0x2a, 0xd5, 0x26, 0xdc,
0xaf, 0xd3, 0x38, 0x95, 0xe1, 0xa9, 0x47, 0x30, 0x5c, 0x5b, 0x16, 0x7f, 0x2e, 0x7c, 0x6f, 0x99,
0x15, 0x81, 0xa6, 0x52, 0xee, 0x47, 0x31, 0x54, 0x76, 0x0c, 0x2e, 0xd7, 0x74, 0x21, 0x4e, 0x50,
0xdf, 0xec, 0xdd, 0x4c, 0xf2, 0x94, 0xc9, 0x74, 0xb8, 0x9e, 0xbc, 0xa2, 0x5b, 0x5a, 0xb3, 0xc0,
0xbe, 0xb5, 0x0d, 0xfa, 0xf7, 0x82, 0xaf, 0xde, 0x14, 0x33, 0xd9, 0x0c, 0xa2, 0xa8, 0x9d, 0x65,
0x1e, 0x75, 0xd6, 0x7e, 0xbc, 0x7c, 0x3e, 0x36, 0xf5, 0xa1, 0x65, 0xee, 0x61, 0x32, 0x61, 0x29,
0x39, 0xc1, 0xec, 0xd3, 0x99, 0xe4, 0x60, 0x74, 0xb9, 0x96, 0xd9, 0x3a, 0x88, 0xe0, 0x1e, 0x0a,
};
const unsigned char c_icc_exp[] = {
0x03,
0x03,
};
const unsigned char c_sdad_cr[] = {
0x1c, 0x00, 0x9f, 0xc4, 0x86, 0x79, 0x15, 0x7d, 0xbf, 0xf4, 0x5f, 0x65, 0xd3, 0x3f, 0xf7, 0x8d,
0x4f, 0xcb, 0xf0, 0xcf, 0x5e, 0xa4, 0x20, 0x8d, 0x10, 0x7a, 0xe9, 0x5a, 0xa3, 0x8c, 0x54, 0x6d,
0x0e, 0x5a, 0x18, 0xb8, 0x74, 0x03, 0xa1, 0x2b, 0xd4, 0x47, 0xa8, 0xbb, 0xfc, 0x1e, 0x49, 0xce,
0x0b, 0x2e, 0x25, 0x13, 0x89, 0x20, 0x57, 0x03, 0xc9, 0xbb, 0x1a, 0x88, 0xcc, 0x79, 0xf1, 0xdd,
0xc2, 0xf9, 0x84, 0x1e, 0xad, 0xf0, 0x7c, 0xe0, 0x7b, 0x62, 0x51, 0x1d, 0xdc, 0x93, 0xdf, 0x59,
0xf2, 0x8f, 0x0e, 0x91, 0xf9, 0x23, 0x32, 0xd2, 0x9c, 0xde, 0xf2, 0xbc, 0xcb, 0x10, 0x08, 0x85,
0x05, 0x00, 0xef, 0x3e, 0x47, 0x0a, 0x4c, 0xb1, 0x8c, 0xd9, 0x1a, 0xa5, 0xc1, 0xa1, 0x08, 0xf3,
0x1c, 0x00, 0x9f, 0xc4, 0x86, 0x79, 0x15, 0x7d, 0xbf, 0xf4, 0x5f, 0x65, 0xd3, 0x3f, 0xf7, 0x8d,
0x4f, 0xcb, 0xf0, 0xcf, 0x5e, 0xa4, 0x20, 0x8d, 0x10, 0x7a, 0xe9, 0x5a, 0xa3, 0x8c, 0x54, 0x6d,
0x0e, 0x5a, 0x18, 0xb8, 0x74, 0x03, 0xa1, 0x2b, 0xd4, 0x47, 0xa8, 0xbb, 0xfc, 0x1e, 0x49, 0xce,
0x0b, 0x2e, 0x25, 0x13, 0x89, 0x20, 0x57, 0x03, 0xc9, 0xbb, 0x1a, 0x88, 0xcc, 0x79, 0xf1, 0xdd,
0xc2, 0xf9, 0x84, 0x1e, 0xad, 0xf0, 0x7c, 0xe0, 0x7b, 0x62, 0x51, 0x1d, 0xdc, 0x93, 0xdf, 0x59,
0xf2, 0x8f, 0x0e, 0x91, 0xf9, 0x23, 0x32, 0xd2, 0x9c, 0xde, 0xf2, 0xbc, 0xcb, 0x10, 0x08, 0x85,
0x05, 0x00, 0xef, 0x3e, 0x47, 0x0a, 0x4c, 0xb1, 0x8c, 0xd9, 0x1a, 0xa5, 0xc1, 0xa1, 0x08, 0xf3,
};
const unsigned char c_ssd1[] = {
0x5f, 0x25, 0x03, 0x14, 0x05, 0x01, 0x5f, 0x24, 0x03, 0x15, 0x06, 0x30, 0x5a, 0x08, 0x52, 0x85,
0x88, 0x12, 0x54, 0x34, 0x56, 0x53, 0x5f, 0x34, 0x01, 0x01, 0x8e, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x1f, 0x03, 0x9f, 0x07, 0x02, 0xff, 0x00, 0x9f, 0x0d, 0x05,
0xbc, 0x50, 0xbc, 0x00, 0x00, 0x9f, 0x0e, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x05,
0xbc, 0x70, 0xbc, 0x98, 0x00, 0x9f, 0x4a, 0x01, 0x82, 0x5f, 0x28, 0x02, 0x06, 0x43, 0x8c, 0x21,
0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03,
0x9c, 0x01, 0x9f, 0x37, 0x04, 0x9f, 0x35, 0x01, 0x9f, 0x45, 0x02, 0x9f, 0x4c, 0x08, 0x9f, 0x34,
0x03, 0x8d, 0x0c, 0x91, 0x0a, 0x8a, 0x02, 0x95, 0x05, 0x9f, 0x37, 0x04, 0x9f, 0x4c, 0x08,
0x39, 0x00,
0x5f, 0x25, 0x03, 0x14, 0x05, 0x01, 0x5f, 0x24, 0x03, 0x15, 0x06, 0x30, 0x5a, 0x08, 0x52, 0x85,
0x88, 0x12, 0x54, 0x34, 0x56, 0x53, 0x5f, 0x34, 0x01, 0x01, 0x8e, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x1f, 0x03, 0x9f, 0x07, 0x02, 0xff, 0x00, 0x9f, 0x0d, 0x05,
0xbc, 0x50, 0xbc, 0x00, 0x00, 0x9f, 0x0e, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x05,
0xbc, 0x70, 0xbc, 0x98, 0x00, 0x9f, 0x4a, 0x01, 0x82, 0x5f, 0x28, 0x02, 0x06, 0x43, 0x8c, 0x21,
0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03,
0x9c, 0x01, 0x9f, 0x37, 0x04, 0x9f, 0x35, 0x01, 0x9f, 0x45, 0x02, 0x9f, 0x4c, 0x08, 0x9f, 0x34,
0x03, 0x8d, 0x0c, 0x91, 0x0a, 0x8a, 0x02, 0x95, 0x05, 0x9f, 0x37, 0x04, 0x9f, 0x4c, 0x08,
0x39, 0x00,
};
static const struct tlv ssd1_tlv = {
.len = sizeof(c_ssd1),
.value = c_ssd1,
.len = sizeof(c_ssd1),
.value = c_ssd1,
};
const unsigned char c_pan[] = {
0x52, 0x85, 0x88, 0x12, 0x54, 0x34, 0x56, 0x53,
0x52, 0x85, 0x88, 0x12, 0x54, 0x34, 0x56, 0x53,
};
const unsigned char c_dd1[] = {
0x12, 0x34, 0x57, 0x79,
0x12, 0x34, 0x57, 0x79,
};
const unsigned char c_dd2[] = {
0x9f, 0x27, 0x01, 0x40, 0x9f, 0x36, 0x02, 0x00, 0x10, 0x9f, 0x10, 0x12, 0x00, 0x10, 0x90, 0x40,
0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x9f, 0x27, 0x01, 0x40, 0x9f, 0x36, 0x02, 0x00, 0x10, 0x9f, 0x10, 0x12, 0x00, 0x10, 0x90, 0x40,
0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
};
const unsigned char c_crm1[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x43, 0x14, 0x09, 0x25, 0x50, 0x12, 0x34, 0x57, 0x79, 0x23, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x43, 0x14, 0x09, 0x25, 0x50, 0x12, 0x34, 0x57, 0x79, 0x23, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x00,
};
static const struct tlv crm1_tlv = {
.len = sizeof(c_crm1),
.value = c_crm1,
.len = sizeof(c_crm1),
.value = c_crm1,
};
static int cda_test_raw(bool verbose)
{
const struct emv_pk *pk = &c_mchip_05;
const struct emv_pk *pk = &c_mchip_05;
struct crypto_pk *kcp = crypto_pk_open(PK_RSA,
pk->modulus, pk->mlen,
pk->exp, pk->elen);
if (!kcp)
return 1;
struct crypto_pk *kcp = crypto_pk_open(PK_RSA,
pk->modulus, pk->mlen,
pk->exp, pk->elen);
if (!kcp)
return 1;
unsigned char *ipk_data;
size_t ipk_data_len;
ipk_data = crypto_pk_encrypt(kcp, c_issuer_cert, sizeof(c_issuer_cert), &ipk_data_len);
crypto_pk_close(kcp);
unsigned char *ipk_data;
size_t ipk_data_len;
ipk_data = crypto_pk_encrypt(kcp, c_issuer_cert, sizeof(c_issuer_cert), &ipk_data_len);
crypto_pk_close(kcp);
if (!ipk_data)
return 1;
if (!ipk_data)
return 1;
if (verbose) {
printf("issuer cert:\n");
dump_buffer(ipk_data, ipk_data_len, stdout, 0);
}
if (verbose) {
printf("issuer cert:\n");
dump_buffer(ipk_data, ipk_data_len, stdout, 0);
}
size_t ipk_pk_len = ipk_data[13];
unsigned char *ipk_pk = malloc(ipk_pk_len);
memcpy(ipk_pk, ipk_data + 15, ipk_data_len - 36);
memcpy(ipk_pk + ipk_data_len - 36, c_issuer_rem, sizeof(c_issuer_rem));
size_t ipk_pk_len = ipk_data[13];
unsigned char *ipk_pk = malloc(ipk_pk_len);
memcpy(ipk_pk, ipk_data + 15, ipk_data_len - 36);
memcpy(ipk_pk + ipk_data_len - 36, c_issuer_rem, sizeof(c_issuer_rem));
struct crypto_hash *ch;
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(ipk_pk);
free(ipk_data);
return 1;
}
struct crypto_hash *ch;
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(ipk_pk);
free(ipk_data);
return 1;
}
crypto_hash_write(ch, ipk_data + 1, 14);
crypto_hash_write(ch, ipk_pk, ipk_pk_len);
crypto_hash_write(ch, c_issuer_exp, sizeof(c_issuer_exp));
crypto_hash_write(ch, ipk_data + 1, 14);
crypto_hash_write(ch, ipk_pk, ipk_pk_len);
crypto_hash_write(ch, c_issuer_exp, sizeof(c_issuer_exp));
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
if (verbose) {
printf("crypto hash:\n");
dump_buffer(h, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash:\n");
dump_buffer(h, 20, stdout, 0);
}
if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
crypto_hash_close(ch);
free(ipk_data);
crypto_hash_close(ch);
free(ipk_data);
struct crypto_pk *ikcp = crypto_pk_open(PK_RSA, ipk_pk, (int) ipk_pk_len,
c_issuer_exp, (int) sizeof(c_issuer_exp));
free(ipk_pk);
if (!ikcp)
return 1;
struct crypto_pk *ikcp = crypto_pk_open(PK_RSA, ipk_pk, (int) ipk_pk_len,
c_issuer_exp, (int) sizeof(c_issuer_exp));
free(ipk_pk);
if (!ikcp)
return 1;
unsigned char *iccpk_data;
size_t iccpk_data_len;
iccpk_data = crypto_pk_encrypt(ikcp, c_icc_cert, sizeof(c_icc_cert), &iccpk_data_len);
crypto_pk_close(ikcp);
unsigned char *iccpk_data;
size_t iccpk_data_len;
iccpk_data = crypto_pk_encrypt(ikcp, c_icc_cert, sizeof(c_icc_cert), &iccpk_data_len);
crypto_pk_close(ikcp);
if (!iccpk_data)
return 1;
if (!iccpk_data)
return 1;
if (verbose) {
printf("icc cert:\n");
dump_buffer(iccpk_data, iccpk_data_len, stdout, 0);
}
if (verbose) {
printf("icc cert:\n");
dump_buffer(iccpk_data, iccpk_data_len, stdout, 0);
}
size_t iccpk_pk_len = iccpk_data[19];
unsigned char *iccpk_pk = malloc(iccpk_pk_len);
memcpy(iccpk_pk, iccpk_data + 21, /*iccpk_data_len - 36*/iccpk_pk_len);
/*memcpy(iccpk_pk + iccpk_data_len - 36, icc_rem, sizeof(icc_rem));*/
size_t iccpk_pk_len = iccpk_data[19];
unsigned char *iccpk_pk = malloc(iccpk_pk_len);
memcpy(iccpk_pk, iccpk_data + 21, /*iccpk_data_len - 36*/iccpk_pk_len);
/*memcpy(iccpk_pk + iccpk_data_len - 36, icc_rem, sizeof(icc_rem));*/
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(iccpk_pk);
free(iccpk_data);
return 1;
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(iccpk_pk);
free(iccpk_data);
return 1;
}
crypto_hash_write(ch, iccpk_data + 1, iccpk_data_len - 22);
crypto_hash_write(ch, c_icc_exp, sizeof(c_icc_exp));
crypto_hash_write(ch, c_ssd1, sizeof(c_ssd1));
crypto_hash_write(ch, iccpk_data + 1, iccpk_data_len - 22);
crypto_hash_write(ch, c_icc_exp, sizeof(c_icc_exp));
crypto_hash_write(ch, c_ssd1, sizeof(c_ssd1));
h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(iccpk_pk);
free(iccpk_data);
return 1;
}
h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(iccpk_pk);
free(iccpk_data);
return 1;
}
if (verbose) {
printf("crypto hash1.1:\n");
dump_buffer(h, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash1.1:\n");
dump_buffer(h, 20, stdout, 0);
}
if (memcmp(iccpk_data + iccpk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(iccpk_pk);
free(iccpk_data);
return 1;
}
if (memcmp(iccpk_data + iccpk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(iccpk_pk);
free(iccpk_data);
return 1;
}
crypto_hash_close(ch);
free(iccpk_data);
crypto_hash_close(ch);
free(iccpk_data);
struct crypto_pk *icckcp = crypto_pk_open(PK_RSA, iccpk_pk, (int) iccpk_pk_len,
c_issuer_exp, (int) sizeof(c_issuer_exp));
free(iccpk_pk);
if (!icckcp)
return 1;
struct crypto_pk *icckcp = crypto_pk_open(PK_RSA, iccpk_pk, (int) iccpk_pk_len,
c_issuer_exp, (int) sizeof(c_issuer_exp));
free(iccpk_pk);
if (!icckcp)
return 1;
size_t sdad_len;
unsigned char *sdad = crypto_pk_encrypt(icckcp, c_sdad_cr, sizeof(c_sdad_cr), &sdad_len);
crypto_pk_close(icckcp);
if (!sdad)
return 1;
size_t sdad_len;
unsigned char *sdad = crypto_pk_encrypt(icckcp, c_sdad_cr, sizeof(c_sdad_cr), &sdad_len);
crypto_pk_close(icckcp);
if (!sdad)
return 1;
if (verbose) {
printf("SDAD:\n");
dump_buffer(sdad, sdad_len, stdout, 0);
}
if (verbose) {
printf("SDAD:\n");
dump_buffer(sdad, sdad_len, stdout, 0);
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(sdad);
return 1;
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(sdad);
return 1;
}
crypto_hash_write(ch, sdad + 1, sdad_len - 22);
crypto_hash_write(ch, c_dd1, sizeof(c_dd1));
crypto_hash_write(ch, sdad + 1, sdad_len - 22);
crypto_hash_write(ch, c_dd1, sizeof(c_dd1));
unsigned char *h2 = crypto_hash_read(ch);
if (!h2) {
crypto_hash_close(ch);
free(sdad);
return 1;
}
unsigned char *h2 = crypto_hash_read(ch);
if (!h2) {
crypto_hash_close(ch);
free(sdad);
return 1;
}
if (verbose) {
printf("crypto hash2:\n");
dump_buffer(h2, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash2:\n");
dump_buffer(h2, 20, stdout, 0);
}
crypto_hash_close(ch);
crypto_hash_close(ch);
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(sdad);
return 1;
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(sdad);
return 1;
}
crypto_hash_write(ch, c_crm1, sizeof(c_crm1));
crypto_hash_write(ch, c_dd2, sizeof(c_dd2));
crypto_hash_write(ch, c_crm1, sizeof(c_crm1));
crypto_hash_write(ch, c_dd2, sizeof(c_dd2));
h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(sdad);
return 1;
}
h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(sdad);
return 1;
}
if (verbose) {
printf("crypto hash2.1:\n");
dump_buffer(h, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash2.1:\n");
dump_buffer(h, 20, stdout, 0);
}
if (memcmp(sdad + 5 + 8 + 1 + 8, h, 20)) {
crypto_hash_close(ch);
free(sdad);
return 1;
}
if (memcmp(sdad + 5 + 8 + 1 + 8, h, 20)) {
crypto_hash_close(ch);
free(sdad);
return 1;
}
crypto_hash_close(ch);
crypto_hash_close(ch);
free(sdad);
free(sdad);
return 0;
return 0;
}
static int cda_test_pk(bool verbose)
{
const struct emv_pk *pk = &c_mchip_05;
struct tlvdb *db;
const struct emv_pk *pk = &c_mchip_05;
struct tlvdb *db;
db = tlvdb_external(0x90, sizeof(c_issuer_cert), c_issuer_cert);
tlvdb_add(db, tlvdb_external(0x9f32, sizeof(c_issuer_exp), c_issuer_exp));
tlvdb_add(db, tlvdb_external(0x92, sizeof(c_issuer_rem), c_issuer_rem));
tlvdb_add(db, tlvdb_external(0x5a, sizeof(c_pan), c_pan));
db = tlvdb_external(0x90, sizeof(c_issuer_cert), c_issuer_cert);
tlvdb_add(db, tlvdb_external(0x9f32, sizeof(c_issuer_exp), c_issuer_exp));
tlvdb_add(db, tlvdb_external(0x92, sizeof(c_issuer_rem), c_issuer_rem));
tlvdb_add(db, tlvdb_external(0x5a, sizeof(c_pan), c_pan));
struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
if (!ipk) {
fprintf(stderr, "Could not recover Issuer certificate!\n");
tlvdb_free(db);
return 2;
}
struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
if (!ipk) {
fprintf(stderr, "Could not recover Issuer certificate!\n");
tlvdb_free(db);
return 2;
}
tlvdb_add(db, tlvdb_external(0x9f46, sizeof(c_icc_cert), c_icc_cert));
tlvdb_add(db, tlvdb_external(0x9f47, sizeof(c_icc_exp), c_icc_exp));
/*tlvdb_add(db, tlvdb_external(0x9f48, sizeof(issuer_rem), issuer_rem));*/
tlvdb_add(db, tlvdb_external(0x9f46, sizeof(c_icc_cert), c_icc_cert));
tlvdb_add(db, tlvdb_external(0x9f47, sizeof(c_icc_exp), c_icc_exp));
/*tlvdb_add(db, tlvdb_external(0x9f48, sizeof(issuer_rem), issuer_rem));*/
struct emv_pk *iccpk = emv_pki_recover_icc_cert(ipk, db, &ssd1_tlv);
if (!iccpk) {
fprintf(stderr, "Could not recover ICC certificate!\n");
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
struct emv_pk *iccpk = emv_pki_recover_icc_cert(ipk, db, &ssd1_tlv);
if (!iccpk) {
fprintf(stderr, "Could not recover ICC certificate!\n");
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
tlvdb_add(db, tlvdb_fixed(0x9f37, sizeof(c_dd1), c_dd1));
tlvdb_add(db, tlvdb_fixed(0x9f37, sizeof(c_dd1), c_dd1));
struct tlvdb *cda_db;
cda_db = tlvdb_fixed(0x9f27, 1, (unsigned char[]){ 0x40 });
tlvdb_add(cda_db, tlvdb_fixed(0x9f36, 2, (unsigned char[]) { 0x00, 0x10 }));
tlvdb_add(cda_db, tlvdb_external(0x9f4b, sizeof(c_sdad_cr), c_sdad_cr));
tlvdb_add(cda_db, tlvdb_fixed(0x9f10, 0x12,
(unsigned char[]) { 0x00, 0x10, 0x90, 0x40, 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}));
struct tlvdb *cda_db;
cda_db = tlvdb_fixed(0x9f27, 1, (unsigned char[]){ 0x40 });
tlvdb_add(cda_db, tlvdb_fixed(0x9f36, 2, (unsigned char[]) { 0x00, 0x10 }));
tlvdb_add(cda_db, tlvdb_external(0x9f4b, sizeof(c_sdad_cr), c_sdad_cr));
tlvdb_add(cda_db, tlvdb_fixed(0x9f10, 0x12,
(unsigned char[]) { 0x00, 0x10, 0x90, 0x40, 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}));
struct tlvdb *idndb = emv_pki_perform_cda(iccpk, db, cda_db,
NULL,
&crm1_tlv,
NULL);
if (!idndb) {
fprintf(stderr, "Could not recover IDN!\n");
tlvdb_free(cda_db);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
struct tlvdb *idndb = emv_pki_perform_cda(iccpk, db, cda_db,
NULL,
&crm1_tlv,
NULL);
if (!idndb) {
fprintf(stderr, "Could not recover IDN!\n");
tlvdb_free(cda_db);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
const struct tlv *idn = tlvdb_get(idndb, 0x9f4c, NULL);
if (!idn) {
fprintf(stderr, "IDN not found!\n");
tlvdb_free(idndb);
tlvdb_free(cda_db);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
const struct tlv *idn = tlvdb_get(idndb, 0x9f4c, NULL);
if (!idn) {
fprintf(stderr, "IDN not found!\n");
tlvdb_free(idndb);
tlvdb_free(cda_db);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
if (verbose) {
printf("IDN:\n");
dump_buffer(idn->value, idn->len, stdout, 0);
}
if (verbose) {
printf("IDN:\n");
dump_buffer(idn->value, idn->len, stdout, 0);
}
tlvdb_free(idndb);
tlvdb_free(cda_db);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
tlvdb_free(idndb);
tlvdb_free(cda_db);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 0;
return 0;
}
int exec_cda_test(bool verbose)
{
int ret;
fprintf(stdout, "\n");
int ret;
fprintf(stdout, "\n");
ret = cda_test_raw(verbose);
if (ret) {
fprintf(stderr, "CDA raw test: failed\n");
return ret;
}
fprintf(stdout, "CDA raw test: passed\n");
ret = cda_test_raw(verbose);
if (ret) {
fprintf(stderr, "CDA raw test: failed\n");
return ret;
}
fprintf(stdout, "CDA raw test: passed\n");
ret = cda_test_pk(verbose);
if (ret) {
fprintf(stderr, "CDA test pk: failed\n");
return ret;
}
fprintf(stdout, "CDA test pk: passed\n");
ret = cda_test_pk(verbose);
if (ret) {
fprintf(stderr, "CDA test pk: failed\n");
return ret;
}
fprintf(stdout, "CDA test pk: passed\n");
return 0;
return 0;
}

View file

@ -27,301 +27,301 @@
static int test_genkey(unsigned int keylength, unsigned char *msg, size_t msg_len, bool verbose)
{
int ret = 1;
size_t tmp_len, tmp2_len;
unsigned char *tmp, *tmp2;
struct crypto_pk *pk;
int ret = 1;
size_t tmp_len, tmp2_len;
unsigned char *tmp, *tmp2;
struct crypto_pk *pk;
printf("Testing key length %u ", keylength);
uint64_t ms = msclock();
printf("Testing key length %u ", keylength);
uint64_t ms = msclock();
pk = crypto_pk_genkey(PK_RSA, 1, keylength, 3);
if (!pk) {
fprintf(stderr, "ERROR: key generation error.\n");
goto out;
}
pk = crypto_pk_genkey(PK_RSA, 1, keylength, 3);
if (!pk) {
fprintf(stderr, "ERROR: key generation error.\n");
goto out;
}
tmp_len = crypto_pk_get_nbits(pk);
if (tmp_len != keylength) {
fprintf(stderr, "ERROR: crypto_pk_get_nbits.\n");
goto close;
}
tmp_len = crypto_pk_get_nbits(pk);
if (tmp_len != keylength) {
fprintf(stderr, "ERROR: crypto_pk_get_nbits.\n");
goto close;
}
tmp = crypto_pk_decrypt(pk, msg, msg_len, &tmp_len);
if (!tmp) {
fprintf(stderr, "ERROR: crypto_pk_decrypt.\n");
goto close;
}
tmp = crypto_pk_decrypt(pk, msg, msg_len, &tmp_len);
if (!tmp) {
fprintf(stderr, "ERROR: crypto_pk_decrypt.\n");
goto close;
}
tmp2 = crypto_pk_encrypt(pk, tmp, tmp_len, &tmp2_len);
if (!tmp2) {
fprintf(stderr, "ERROR: crypto_pk_encrypt.\n");
goto free_tmp;
}
tmp2 = crypto_pk_encrypt(pk, tmp, tmp_len, &tmp2_len);
if (!tmp2) {
fprintf(stderr, "ERROR: crypto_pk_encrypt.\n");
goto free_tmp;
}
if (tmp2_len == msg_len && !memcmp(tmp2, msg, tmp2_len)) {
ret = 0;
} else {
fprintf(stderr, "ERROR: encrypt-decrypt sequence length or data error.\n");
}
if (tmp2_len == msg_len && !memcmp(tmp2, msg, tmp2_len)) {
ret = 0;
} else {
fprintf(stderr, "ERROR: encrypt-decrypt sequence length or data error.\n");
}
free(tmp2);
printf("passed. (%"PRIu64" ms) \n", msclock() - ms);
free(tmp2);
printf("passed. (%"PRIu64" ms) \n", msclock() - ms);
free_tmp:
free(tmp);
free(tmp);
close:
crypto_pk_close(pk);
crypto_pk_close(pk);
out:
return ret;
return ret;
}
static unsigned char message[4096 / 8] =
"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb"
"ccccccccccccccccdddddddddddddddd"
"eeeeeeeeeeeeeeeeffffffffffffffff"
"gggggggggggggggghhhhhhhhhhhhhhhh"
"iiiiiiiiiiiiiiiijjjjjjjjjjjjjjjj"
"kkkkkkkkkkkkkkkkllllllllllllllll"
"mmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnn"
"oooooooooooooooopppppppppppppppp"
"qqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrr"
"sssssssssssssssstttttttttttttttt"
"uuuuuuuuuuuuuuuuvvvvvvvvvvvvvvvv"
"wwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxx"
"yyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzz"
"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb"
"ccccccccccccccccdddddddddddddddd"
"eeeeeeeeeeeeeeeeffffffffffffffff"
;
"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb"
"ccccccccccccccccdddddddddddddddd"
"eeeeeeeeeeeeeeeeffffffffffffffff"
"gggggggggggggggghhhhhhhhhhhhhhhh"
"iiiiiiiiiiiiiiiijjjjjjjjjjjjjjjj"
"kkkkkkkkkkkkkkkkllllllllllllllll"
"mmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnn"
"oooooooooooooooopppppppppppppppp"
"qqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrr"
"sssssssssssssssstttttttttttttttt"
"uuuuuuuuuuuuuuuuvvvvvvvvvvvvvvvv"
"wwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxx"
"yyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzz"
"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb"
"ccccccccccccccccdddddddddddddddd"
"eeeeeeeeeeeeeeeeffffffffffffffff"
;
static unsigned char pk_N[] = {
0xdb, 0x12, 0xe4, 0xf1, 0x8d, 0x43, 0x74, 0xf0, 0xec, 0x38, 0xdc, 0xfb, 0xf9, 0x20, 0x75, 0x6d,
0x05, 0xf4, 0x36, 0xc2, 0x21, 0xac, 0x34, 0x0d, 0x16, 0xc5, 0x23, 0xcb, 0xfc, 0x9a, 0x8a, 0xd1,
0xe0, 0xbd, 0xda, 0xe5, 0x77, 0xd5, 0xaf, 0x65, 0x8d, 0x6b, 0x62, 0x5c, 0xcd, 0x89, 0x06, 0x8d,
0x11, 0x19, 0x6b, 0x0e, 0x3e, 0xe2, 0x80, 0x45, 0xf6, 0x44, 0x55, 0x21, 0x9c, 0x86, 0x90, 0x00,
0xa8, 0xaf, 0x8c, 0x94, 0xde, 0x3f, 0xe8, 0x56, 0x52, 0xfe, 0xee, 0xa5, 0x36, 0x72, 0x07, 0xf2,
0xcf, 0x8e, 0xf0, 0xbd, 0xff, 0x36, 0xd5, 0xf2, 0xad, 0x74, 0x1d, 0x17, 0xd0, 0xb7, 0x93, 0xe2,
0x2c, 0x8d, 0x3f, 0xb6, 0x7c, 0x65, 0x19, 0x9f, 0xa7, 0x80, 0x1f, 0x9f, 0xe5, 0x2f, 0x2d, 0x75,
0xc9, 0xc2, 0xe9, 0x70, 0xfa, 0x1e, 0x5a, 0xc6, 0xa3, 0x82, 0xd1, 0x29, 0x5a, 0x60, 0xce, 0x1f,
0x40, 0x2e, 0xfc, 0x2a, 0x5e, 0xde, 0xc9, 0x67, 0xfc, 0x45, 0x18, 0xce, 0xf2, 0x83, 0x94, 0x53,
0xd6, 0x4f, 0x2e, 0xc5, 0x2d, 0xa1, 0xa5, 0x7a, 0x63, 0x26, 0x70, 0xcb, 0x76, 0xfc, 0xb5, 0x8d,
0x0f, 0x88, 0x4c, 0x07, 0xba, 0xfa, 0x8b, 0xbc, 0xa0, 0xea, 0xea, 0x0a, 0xe6, 0xa5, 0x44, 0xa5,
0x0d, 0x12, 0x66, 0x2b, 0xf7, 0xc4, 0x76, 0xa3, 0x82, 0xa6, 0x2b, 0xb2, 0x5a, 0x27, 0xcd, 0x11,
0xd2, 0x9d, 0x42, 0x86, 0x8c, 0x82, 0xc8, 0xe1, 0xff, 0x7d, 0xf1, 0xd9, 0xd9, 0xa1, 0xf3, 0x3d,
0xc3, 0x12, 0x4e, 0x47, 0xc8, 0xa2, 0xcd, 0x72, 0x5a, 0x18, 0xea, 0x89, 0x5c, 0x73, 0x28, 0x52,
0xf8, 0xdb, 0x70, 0xdc, 0x92, 0xc9, 0xb7, 0x98, 0x10, 0x94, 0x79, 0xdc, 0x9e, 0x12, 0x6c, 0x14,
0x78, 0xf9, 0x5a, 0xad, 0x00, 0x98, 0xc8, 0x17, 0x79, 0x8a, 0xed, 0xe7, 0xc3, 0xd3, 0xa7, 0x8b,
0xdb, 0x12, 0xe4, 0xf1, 0x8d, 0x43, 0x74, 0xf0, 0xec, 0x38, 0xdc, 0xfb, 0xf9, 0x20, 0x75, 0x6d,
0x05, 0xf4, 0x36, 0xc2, 0x21, 0xac, 0x34, 0x0d, 0x16, 0xc5, 0x23, 0xcb, 0xfc, 0x9a, 0x8a, 0xd1,
0xe0, 0xbd, 0xda, 0xe5, 0x77, 0xd5, 0xaf, 0x65, 0x8d, 0x6b, 0x62, 0x5c, 0xcd, 0x89, 0x06, 0x8d,
0x11, 0x19, 0x6b, 0x0e, 0x3e, 0xe2, 0x80, 0x45, 0xf6, 0x44, 0x55, 0x21, 0x9c, 0x86, 0x90, 0x00,
0xa8, 0xaf, 0x8c, 0x94, 0xde, 0x3f, 0xe8, 0x56, 0x52, 0xfe, 0xee, 0xa5, 0x36, 0x72, 0x07, 0xf2,
0xcf, 0x8e, 0xf0, 0xbd, 0xff, 0x36, 0xd5, 0xf2, 0xad, 0x74, 0x1d, 0x17, 0xd0, 0xb7, 0x93, 0xe2,
0x2c, 0x8d, 0x3f, 0xb6, 0x7c, 0x65, 0x19, 0x9f, 0xa7, 0x80, 0x1f, 0x9f, 0xe5, 0x2f, 0x2d, 0x75,
0xc9, 0xc2, 0xe9, 0x70, 0xfa, 0x1e, 0x5a, 0xc6, 0xa3, 0x82, 0xd1, 0x29, 0x5a, 0x60, 0xce, 0x1f,
0x40, 0x2e, 0xfc, 0x2a, 0x5e, 0xde, 0xc9, 0x67, 0xfc, 0x45, 0x18, 0xce, 0xf2, 0x83, 0x94, 0x53,
0xd6, 0x4f, 0x2e, 0xc5, 0x2d, 0xa1, 0xa5, 0x7a, 0x63, 0x26, 0x70, 0xcb, 0x76, 0xfc, 0xb5, 0x8d,
0x0f, 0x88, 0x4c, 0x07, 0xba, 0xfa, 0x8b, 0xbc, 0xa0, 0xea, 0xea, 0x0a, 0xe6, 0xa5, 0x44, 0xa5,
0x0d, 0x12, 0x66, 0x2b, 0xf7, 0xc4, 0x76, 0xa3, 0x82, 0xa6, 0x2b, 0xb2, 0x5a, 0x27, 0xcd, 0x11,
0xd2, 0x9d, 0x42, 0x86, 0x8c, 0x82, 0xc8, 0xe1, 0xff, 0x7d, 0xf1, 0xd9, 0xd9, 0xa1, 0xf3, 0x3d,
0xc3, 0x12, 0x4e, 0x47, 0xc8, 0xa2, 0xcd, 0x72, 0x5a, 0x18, 0xea, 0x89, 0x5c, 0x73, 0x28, 0x52,
0xf8, 0xdb, 0x70, 0xdc, 0x92, 0xc9, 0xb7, 0x98, 0x10, 0x94, 0x79, 0xdc, 0x9e, 0x12, 0x6c, 0x14,
0x78, 0xf9, 0x5a, 0xad, 0x00, 0x98, 0xc8, 0x17, 0x79, 0x8a, 0xed, 0xe7, 0xc3, 0xd3, 0xa7, 0x8b,
};
static unsigned char pk_E[] = {
0x01, 0x00, 0x01,
0x01, 0x00, 0x01,
};
static unsigned char pk_D[] = {
0x01, 0x17, 0xd4, 0x0a, 0x9c, 0x80, 0xd4, 0xa9, 0x8b, 0x14, 0x31, 0x8e, 0x14, 0x4d, 0x24, 0x28,
0xda, 0x19, 0xc0, 0xd8, 0x31, 0x20, 0xd1, 0xd5, 0xaa, 0xe2, 0x6a, 0xee, 0x4e, 0xa1, 0x5a, 0xc5,
0xf7, 0x50, 0x1b, 0x32, 0x7f, 0xe9, 0x92, 0x09, 0x78, 0xae, 0x2b, 0x7c, 0x79, 0x0e, 0x10, 0xf9,
0x4d, 0x37, 0x8a, 0x40, 0x34, 0xf2, 0x1e, 0x5f, 0xba, 0xfd, 0xd6, 0x4a, 0xe7, 0xa4, 0x08, 0x3d,
0xe8, 0x99, 0x8f, 0xa3, 0x02, 0x84, 0xe1, 0x1c, 0xe5, 0x27, 0x1e, 0x7b, 0xb6, 0x8c, 0xd5, 0x1b,
0x52, 0x0b, 0xcd, 0x89, 0xb5, 0x27, 0x49, 0xe3, 0xff, 0x17, 0x90, 0x39, 0x99, 0x32, 0x01, 0x4b,
0xe4, 0x9b, 0x03, 0xd1, 0x5e, 0x47, 0x86, 0xdc, 0x34, 0x12, 0xc0, 0x95, 0xa4, 0xa8, 0x1a, 0x9a,
0xf6, 0xd9, 0xc1, 0x1e, 0x6e, 0x31, 0x0e, 0x94, 0xe5, 0x25, 0xf6, 0xf3, 0x34, 0xdf, 0x3c, 0xc8,
0x0a, 0xc5, 0x8c, 0x00, 0x5c, 0x59, 0x55, 0x06, 0xd1, 0x39, 0x84, 0x35, 0x96, 0x40, 0xe8, 0xb2,
0xf7, 0x13, 0x83, 0x37, 0xe1, 0xe2, 0x79, 0x41, 0x90, 0x2a, 0xc3, 0x71, 0xc5, 0xcf, 0xf0, 0xaa,
0x01, 0x2f, 0x48, 0x9c, 0x3f, 0x29, 0x7b, 0xb7, 0x5c, 0xef, 0x25, 0xde, 0x34, 0x23, 0x81, 0x7a,
0x4c, 0x3a, 0x9b, 0xe4, 0xa7, 0x44, 0x73, 0xbf, 0xf7, 0x39, 0x43, 0xa4, 0x39, 0xa0, 0x1b, 0xf7,
0x4f, 0x5f, 0x14, 0x49, 0x32, 0x0e, 0x66, 0xd0, 0x29, 0xb5, 0x80, 0xe0, 0xba, 0x3b, 0x88, 0x2b,
0x14, 0xa4, 0x26, 0x00, 0x2f, 0x50, 0x20, 0x4e, 0xfa, 0xc2, 0x44, 0x72, 0x72, 0x6c, 0x2a, 0x77,
0x85, 0x20, 0xe0, 0x1d, 0x95, 0x6a, 0x66, 0xe7, 0xb8, 0xca, 0x5b, 0xc9, 0xc3, 0xf3, 0x39, 0xef,
0xd7, 0xd5, 0x45, 0xb6, 0x3e, 0x19, 0xea, 0x7c, 0x56, 0x20, 0x1b, 0x95, 0x86, 0x2e, 0xc7, 0x51,
0x01, 0x17, 0xd4, 0x0a, 0x9c, 0x80, 0xd4, 0xa9, 0x8b, 0x14, 0x31, 0x8e, 0x14, 0x4d, 0x24, 0x28,
0xda, 0x19, 0xc0, 0xd8, 0x31, 0x20, 0xd1, 0xd5, 0xaa, 0xe2, 0x6a, 0xee, 0x4e, 0xa1, 0x5a, 0xc5,
0xf7, 0x50, 0x1b, 0x32, 0x7f, 0xe9, 0x92, 0x09, 0x78, 0xae, 0x2b, 0x7c, 0x79, 0x0e, 0x10, 0xf9,
0x4d, 0x37, 0x8a, 0x40, 0x34, 0xf2, 0x1e, 0x5f, 0xba, 0xfd, 0xd6, 0x4a, 0xe7, 0xa4, 0x08, 0x3d,
0xe8, 0x99, 0x8f, 0xa3, 0x02, 0x84, 0xe1, 0x1c, 0xe5, 0x27, 0x1e, 0x7b, 0xb6, 0x8c, 0xd5, 0x1b,
0x52, 0x0b, 0xcd, 0x89, 0xb5, 0x27, 0x49, 0xe3, 0xff, 0x17, 0x90, 0x39, 0x99, 0x32, 0x01, 0x4b,
0xe4, 0x9b, 0x03, 0xd1, 0x5e, 0x47, 0x86, 0xdc, 0x34, 0x12, 0xc0, 0x95, 0xa4, 0xa8, 0x1a, 0x9a,
0xf6, 0xd9, 0xc1, 0x1e, 0x6e, 0x31, 0x0e, 0x94, 0xe5, 0x25, 0xf6, 0xf3, 0x34, 0xdf, 0x3c, 0xc8,
0x0a, 0xc5, 0x8c, 0x00, 0x5c, 0x59, 0x55, 0x06, 0xd1, 0x39, 0x84, 0x35, 0x96, 0x40, 0xe8, 0xb2,
0xf7, 0x13, 0x83, 0x37, 0xe1, 0xe2, 0x79, 0x41, 0x90, 0x2a, 0xc3, 0x71, 0xc5, 0xcf, 0xf0, 0xaa,
0x01, 0x2f, 0x48, 0x9c, 0x3f, 0x29, 0x7b, 0xb7, 0x5c, 0xef, 0x25, 0xde, 0x34, 0x23, 0x81, 0x7a,
0x4c, 0x3a, 0x9b, 0xe4, 0xa7, 0x44, 0x73, 0xbf, 0xf7, 0x39, 0x43, 0xa4, 0x39, 0xa0, 0x1b, 0xf7,
0x4f, 0x5f, 0x14, 0x49, 0x32, 0x0e, 0x66, 0xd0, 0x29, 0xb5, 0x80, 0xe0, 0xba, 0x3b, 0x88, 0x2b,
0x14, 0xa4, 0x26, 0x00, 0x2f, 0x50, 0x20, 0x4e, 0xfa, 0xc2, 0x44, 0x72, 0x72, 0x6c, 0x2a, 0x77,
0x85, 0x20, 0xe0, 0x1d, 0x95, 0x6a, 0x66, 0xe7, 0xb8, 0xca, 0x5b, 0xc9, 0xc3, 0xf3, 0x39, 0xef,
0xd7, 0xd5, 0x45, 0xb6, 0x3e, 0x19, 0xea, 0x7c, 0x56, 0x20, 0x1b, 0x95, 0x86, 0x2e, 0xc7, 0x51,
};
static unsigned char pk_P[] = {
0xf5, 0x93, 0x0f, 0x76, 0x00, 0xab, 0x37, 0x01, 0xb9, 0x52, 0xb6, 0x82, 0xf9, 0xf5, 0xae, 0x29,
0x8f, 0xd5, 0x08, 0xbc, 0xf7, 0x9f, 0x84, 0xb6, 0x4c, 0x94, 0xb5, 0xfc, 0xfe, 0xe1, 0xcd, 0x6a,
0xf4, 0x9c, 0xa7, 0x33, 0xdb, 0xd8, 0xc8, 0xc1, 0xc0, 0x8d, 0x65, 0xed, 0x29, 0x99, 0x6c, 0x5c,
0xbe, 0x08, 0xac, 0x04, 0xe4, 0x3a, 0x18, 0xe2, 0x0f, 0x70, 0x26, 0x70, 0x9b, 0x71, 0xfc, 0x9f,
0x22, 0xea, 0x90, 0x3b, 0xc2, 0xa5, 0x16, 0x7a, 0xcd, 0x04, 0x3e, 0xa6, 0x37, 0x49, 0xa7, 0xee,
0xaa, 0xe4, 0x9d, 0xaa, 0x9b, 0xb0, 0xe2, 0x6a, 0x9d, 0x1e, 0xcd, 0x83, 0x4e, 0xd8, 0x59, 0x6d,
0x03, 0xd5, 0x4c, 0x5e, 0xc5, 0x22, 0x10, 0xb7, 0xcc, 0x0c, 0x90, 0x76, 0x05, 0x21, 0xe7, 0x77,
0x5c, 0x88, 0x5f, 0xd0, 0x5f, 0x9e, 0x2e, 0x49, 0x56, 0xf4, 0x2b, 0xa9, 0x99, 0x57, 0x74, 0x19,
0xf5, 0x93, 0x0f, 0x76, 0x00, 0xab, 0x37, 0x01, 0xb9, 0x52, 0xb6, 0x82, 0xf9, 0xf5, 0xae, 0x29,
0x8f, 0xd5, 0x08, 0xbc, 0xf7, 0x9f, 0x84, 0xb6, 0x4c, 0x94, 0xb5, 0xfc, 0xfe, 0xe1, 0xcd, 0x6a,
0xf4, 0x9c, 0xa7, 0x33, 0xdb, 0xd8, 0xc8, 0xc1, 0xc0, 0x8d, 0x65, 0xed, 0x29, 0x99, 0x6c, 0x5c,
0xbe, 0x08, 0xac, 0x04, 0xe4, 0x3a, 0x18, 0xe2, 0x0f, 0x70, 0x26, 0x70, 0x9b, 0x71, 0xfc, 0x9f,
0x22, 0xea, 0x90, 0x3b, 0xc2, 0xa5, 0x16, 0x7a, 0xcd, 0x04, 0x3e, 0xa6, 0x37, 0x49, 0xa7, 0xee,
0xaa, 0xe4, 0x9d, 0xaa, 0x9b, 0xb0, 0xe2, 0x6a, 0x9d, 0x1e, 0xcd, 0x83, 0x4e, 0xd8, 0x59, 0x6d,
0x03, 0xd5, 0x4c, 0x5e, 0xc5, 0x22, 0x10, 0xb7, 0xcc, 0x0c, 0x90, 0x76, 0x05, 0x21, 0xe7, 0x77,
0x5c, 0x88, 0x5f, 0xd0, 0x5f, 0x9e, 0x2e, 0x49, 0x56, 0xf4, 0x2b, 0xa9, 0x99, 0x57, 0x74, 0x19,
};
static unsigned char pk_Q[] = {
0xe4, 0x5f, 0xd2, 0x28, 0xbd, 0xf3, 0xdd, 0x70, 0x3d, 0xfd, 0x01, 0x23, 0xae, 0x93, 0x6a, 0x91,
0xca, 0x68, 0xb1, 0xdb, 0x81, 0xab, 0x1e, 0x63, 0x76, 0x9b, 0x6d, 0xaa, 0x41, 0x87, 0x5a, 0x79,
0xe7, 0xce, 0xd6, 0x84, 0x32, 0x53, 0xf5, 0xfc, 0xb7, 0x41, 0x7c, 0xcb, 0x88, 0x09, 0xcb, 0xe9,
0x07, 0x16, 0x28, 0x55, 0x23, 0xe5, 0xf2, 0xf5, 0x23, 0xf5, 0xee, 0x2b, 0x9d, 0x91, 0x56, 0xc6,
0x30, 0x91, 0x4d, 0x16, 0x11, 0x6c, 0x48, 0x45, 0xe8, 0x5d, 0x0e, 0x9e, 0x04, 0xc8, 0xb6, 0xdd,
0xba, 0x0d, 0xdf, 0x53, 0x56, 0xfa, 0x0b, 0x0b, 0x99, 0x8d, 0xea, 0x5c, 0x45, 0x7d, 0xed, 0xad,
0x1f, 0xc5, 0xc1, 0x7d, 0x63, 0x31, 0xf8, 0x32, 0xb5, 0x33, 0xb0, 0xef, 0xce, 0x2e, 0x74, 0x1e,
0x77, 0x2a, 0x18, 0x35, 0x3d, 0x6e, 0x01, 0xba, 0xde, 0x21, 0x8e, 0x14, 0x12, 0xc3, 0x0d, 0x43,
0xe4, 0x5f, 0xd2, 0x28, 0xbd, 0xf3, 0xdd, 0x70, 0x3d, 0xfd, 0x01, 0x23, 0xae, 0x93, 0x6a, 0x91,
0xca, 0x68, 0xb1, 0xdb, 0x81, 0xab, 0x1e, 0x63, 0x76, 0x9b, 0x6d, 0xaa, 0x41, 0x87, 0x5a, 0x79,
0xe7, 0xce, 0xd6, 0x84, 0x32, 0x53, 0xf5, 0xfc, 0xb7, 0x41, 0x7c, 0xcb, 0x88, 0x09, 0xcb, 0xe9,
0x07, 0x16, 0x28, 0x55, 0x23, 0xe5, 0xf2, 0xf5, 0x23, 0xf5, 0xee, 0x2b, 0x9d, 0x91, 0x56, 0xc6,
0x30, 0x91, 0x4d, 0x16, 0x11, 0x6c, 0x48, 0x45, 0xe8, 0x5d, 0x0e, 0x9e, 0x04, 0xc8, 0xb6, 0xdd,
0xba, 0x0d, 0xdf, 0x53, 0x56, 0xfa, 0x0b, 0x0b, 0x99, 0x8d, 0xea, 0x5c, 0x45, 0x7d, 0xed, 0xad,
0x1f, 0xc5, 0xc1, 0x7d, 0x63, 0x31, 0xf8, 0x32, 0xb5, 0x33, 0xb0, 0xef, 0xce, 0x2e, 0x74, 0x1e,
0x77, 0x2a, 0x18, 0x35, 0x3d, 0x6e, 0x01, 0xba, 0xde, 0x21, 0x8e, 0x14, 0x12, 0xc3, 0x0d, 0x43,
};
static unsigned char pk_dP[] = {
0x5a, 0xc8, 0xf7, 0x1a, 0x44, 0xbd, 0x07, 0x24, 0xd8, 0x02, 0x3f, 0xfe, 0xc3, 0xb1, 0x93, 0xa5,
0x41, 0xcb, 0x1b, 0xe3, 0xe0, 0x17, 0x54, 0xd4, 0xa0, 0x13, 0x0a, 0x04, 0x71, 0xa5, 0xc0, 0x6f,
0x1d, 0xe7, 0x1b, 0xd9, 0x0c, 0x19, 0x64, 0x7e, 0x5c, 0x54, 0xe9, 0xad, 0x77, 0x87, 0x84, 0x8b,
0xf4, 0xa4, 0xf8, 0x13, 0x06, 0xdc, 0x83, 0x7e, 0x6e, 0xfe, 0xa2, 0xf7, 0x56, 0x40, 0x19, 0x88,
0x2b, 0x3c, 0x53, 0xfe, 0x03, 0xc3, 0x4c, 0x40, 0x31, 0xb2, 0xb4, 0x06, 0x76, 0xc2, 0x00, 0x17,
0x37, 0x8e, 0x34, 0xcb, 0x71, 0xab, 0x3e, 0xc8, 0xf3, 0x35, 0x03, 0xfc, 0xdb, 0x15, 0x18, 0x5a,
0x38, 0xe4, 0x8d, 0xcb, 0x2b, 0x4d, 0xa0, 0xa8, 0x92, 0x02, 0xc3, 0x15, 0x1e, 0x68, 0x9e, 0x4d,
0x7e, 0x23, 0xdc, 0x68, 0x08, 0x31, 0x4e, 0x23, 0x46, 0xc6, 0x15, 0xae, 0x29, 0x46, 0x2f, 0x61,
0x5a, 0xc8, 0xf7, 0x1a, 0x44, 0xbd, 0x07, 0x24, 0xd8, 0x02, 0x3f, 0xfe, 0xc3, 0xb1, 0x93, 0xa5,
0x41, 0xcb, 0x1b, 0xe3, 0xe0, 0x17, 0x54, 0xd4, 0xa0, 0x13, 0x0a, 0x04, 0x71, 0xa5, 0xc0, 0x6f,
0x1d, 0xe7, 0x1b, 0xd9, 0x0c, 0x19, 0x64, 0x7e, 0x5c, 0x54, 0xe9, 0xad, 0x77, 0x87, 0x84, 0x8b,
0xf4, 0xa4, 0xf8, 0x13, 0x06, 0xdc, 0x83, 0x7e, 0x6e, 0xfe, 0xa2, 0xf7, 0x56, 0x40, 0x19, 0x88,
0x2b, 0x3c, 0x53, 0xfe, 0x03, 0xc3, 0x4c, 0x40, 0x31, 0xb2, 0xb4, 0x06, 0x76, 0xc2, 0x00, 0x17,
0x37, 0x8e, 0x34, 0xcb, 0x71, 0xab, 0x3e, 0xc8, 0xf3, 0x35, 0x03, 0xfc, 0xdb, 0x15, 0x18, 0x5a,
0x38, 0xe4, 0x8d, 0xcb, 0x2b, 0x4d, 0xa0, 0xa8, 0x92, 0x02, 0xc3, 0x15, 0x1e, 0x68, 0x9e, 0x4d,
0x7e, 0x23, 0xdc, 0x68, 0x08, 0x31, 0x4e, 0x23, 0x46, 0xc6, 0x15, 0xae, 0x29, 0x46, 0x2f, 0x61,
};
static unsigned char pk_dQ[] = {
0x33, 0x61, 0x9f, 0xae, 0x0c, 0xf6, 0xc6, 0x16, 0x8f, 0xcb, 0xd1, 0xaa, 0xce, 0x87, 0x5a, 0x4d,
0xcc, 0xe5, 0x7b, 0x46, 0xb0, 0xc8, 0xe8, 0x40, 0x66, 0x9a, 0x17, 0xb5, 0x5b, 0xa2, 0xf1, 0x67,
0x46, 0x11, 0x52, 0x50, 0x51, 0xe6, 0x74, 0x0c, 0xd4, 0xca, 0x46, 0x22, 0xa0, 0xcb, 0xdb, 0x75,
0xe5, 0x63, 0x45, 0xd5, 0xca, 0x0a, 0xdd, 0x7b, 0xec, 0x08, 0x53, 0xfa, 0xba, 0x2b, 0xce, 0x03,
0x2f, 0x40, 0x31, 0xc0, 0xca, 0x50, 0xbb, 0x7e, 0x07, 0x06, 0x90, 0xd8, 0x5a, 0xa9, 0x32, 0x03,
0x76, 0xed, 0xd2, 0x16, 0x35, 0x16, 0x72, 0xcf, 0xbc, 0x4f, 0xa2, 0xaf, 0xf9, 0xee, 0x98, 0x40,
0x00, 0x4b, 0x04, 0xfa, 0x8a, 0x0b, 0xdf, 0x14, 0xc1, 0x92, 0x0c, 0xb8, 0x17, 0x82, 0x7a, 0x1b,
0xb4, 0xa1, 0xe2, 0xea, 0x6f, 0x94, 0xc5, 0x8c, 0xde, 0x97, 0x5c, 0x19, 0x06, 0x13, 0x9e, 0x73,
0x33, 0x61, 0x9f, 0xae, 0x0c, 0xf6, 0xc6, 0x16, 0x8f, 0xcb, 0xd1, 0xaa, 0xce, 0x87, 0x5a, 0x4d,
0xcc, 0xe5, 0x7b, 0x46, 0xb0, 0xc8, 0xe8, 0x40, 0x66, 0x9a, 0x17, 0xb5, 0x5b, 0xa2, 0xf1, 0x67,
0x46, 0x11, 0x52, 0x50, 0x51, 0xe6, 0x74, 0x0c, 0xd4, 0xca, 0x46, 0x22, 0xa0, 0xcb, 0xdb, 0x75,
0xe5, 0x63, 0x45, 0xd5, 0xca, 0x0a, 0xdd, 0x7b, 0xec, 0x08, 0x53, 0xfa, 0xba, 0x2b, 0xce, 0x03,
0x2f, 0x40, 0x31, 0xc0, 0xca, 0x50, 0xbb, 0x7e, 0x07, 0x06, 0x90, 0xd8, 0x5a, 0xa9, 0x32, 0x03,
0x76, 0xed, 0xd2, 0x16, 0x35, 0x16, 0x72, 0xcf, 0xbc, 0x4f, 0xa2, 0xaf, 0xf9, 0xee, 0x98, 0x40,
0x00, 0x4b, 0x04, 0xfa, 0x8a, 0x0b, 0xdf, 0x14, 0xc1, 0x92, 0x0c, 0xb8, 0x17, 0x82, 0x7a, 0x1b,
0xb4, 0xa1, 0xe2, 0xea, 0x6f, 0x94, 0xc5, 0x8c, 0xde, 0x97, 0x5c, 0x19, 0x06, 0x13, 0x9e, 0x73,
};
static unsigned char pk_I[] = {
0x75, 0x40, 0xc6, 0x02, 0x7e, 0x4f, 0xad, 0xdb, 0x95, 0xac, 0x07, 0x8d, 0x80, 0xb6, 0x80, 0x02,
0x06, 0xdd, 0xb8, 0x5d, 0x92, 0x65, 0x69, 0x26, 0x86, 0x61, 0x6c, 0x87, 0x4e, 0xe5, 0x03, 0x68,
0xc6, 0x10, 0x15, 0x8c, 0x43, 0x3a, 0x45, 0x63, 0x48, 0xb7, 0x8a, 0x8c, 0xa2, 0x2b, 0x34, 0xb6,
0x83, 0xfe, 0xa8, 0x10, 0xa5, 0x74, 0xa5, 0xa9, 0x52, 0x42, 0x1f, 0xa0, 0x80, 0x6a, 0xc5, 0x35,
0xe8, 0xb8, 0xc2, 0xa0, 0x3f, 0x49, 0x18, 0xcf, 0x0e, 0x54, 0x3c, 0x70, 0x11, 0x11, 0xd3, 0x85,
0x8c, 0xb2, 0xe5, 0x74, 0xdf, 0x98, 0xea, 0x6c, 0xc0, 0x5f, 0x7f, 0xff, 0x69, 0xbf, 0x08, 0x8d,
0x1b, 0xc4, 0x90, 0xcc, 0xa4, 0xcd, 0xcc, 0x34, 0x58, 0xe5, 0x91, 0x53, 0x3a, 0xd5, 0x39, 0xf4,
0xd4, 0x42, 0xc9, 0x17, 0xb2, 0x2c, 0x92, 0x12, 0x37, 0x1b, 0xd3, 0xc5, 0x79, 0xd2, 0x65, 0x61,
0x75, 0x40, 0xc6, 0x02, 0x7e, 0x4f, 0xad, 0xdb, 0x95, 0xac, 0x07, 0x8d, 0x80, 0xb6, 0x80, 0x02,
0x06, 0xdd, 0xb8, 0x5d, 0x92, 0x65, 0x69, 0x26, 0x86, 0x61, 0x6c, 0x87, 0x4e, 0xe5, 0x03, 0x68,
0xc6, 0x10, 0x15, 0x8c, 0x43, 0x3a, 0x45, 0x63, 0x48, 0xb7, 0x8a, 0x8c, 0xa2, 0x2b, 0x34, 0xb6,
0x83, 0xfe, 0xa8, 0x10, 0xa5, 0x74, 0xa5, 0xa9, 0x52, 0x42, 0x1f, 0xa0, 0x80, 0x6a, 0xc5, 0x35,
0xe8, 0xb8, 0xc2, 0xa0, 0x3f, 0x49, 0x18, 0xcf, 0x0e, 0x54, 0x3c, 0x70, 0x11, 0x11, 0xd3, 0x85,
0x8c, 0xb2, 0xe5, 0x74, 0xdf, 0x98, 0xea, 0x6c, 0xc0, 0x5f, 0x7f, 0xff, 0x69, 0xbf, 0x08, 0x8d,
0x1b, 0xc4, 0x90, 0xcc, 0xa4, 0xcd, 0xcc, 0x34, 0x58, 0xe5, 0x91, 0x53, 0x3a, 0xd5, 0x39, 0xf4,
0xd4, 0x42, 0xc9, 0x17, 0xb2, 0x2c, 0x92, 0x12, 0x37, 0x1b, 0xd3, 0xc5, 0x79, 0xd2, 0x65, 0x61,
};
static int test_pk(bool verbose)
{
int ret = 1;
size_t tmp_len, tmp2_len;
unsigned char *tmp, *tmp2;
struct crypto_pk *pubk, *privk;
unsigned char *msg = message;
size_t msg_len = sizeof(pk_N);
int ret = 1;
size_t tmp_len, tmp2_len;
unsigned char *tmp, *tmp2;
struct crypto_pk *pubk, *privk;
unsigned char *msg = message;
size_t msg_len = sizeof(pk_N);
printf("Testing public keys interfaces\n");
printf("Testing public keys interfaces\n");
pubk = crypto_pk_open(PK_RSA,
pk_N, sizeof(pk_N),
pk_E, sizeof(pk_E));
if (!pubk) {
fprintf(stderr, "ERROR: open public key.\n");
return 1;
}
pubk = crypto_pk_open(PK_RSA,
pk_N, sizeof(pk_N),
pk_E, sizeof(pk_E));
if (!pubk) {
fprintf(stderr, "ERROR: open public key.\n");
return 1;
}
tmp_len = crypto_pk_get_nbits(pubk);
if (tmp_len != sizeof(pk_N) * 8) {
fprintf(stderr, "ERROR: crypto_pk_get_nbits mismatch.\n");
goto close_pub;
}
tmp_len = crypto_pk_get_nbits(pubk);
if (tmp_len != sizeof(pk_N) * 8) {
fprintf(stderr, "ERROR: crypto_pk_get_nbits mismatch.\n");
goto close_pub;
}
tmp = crypto_pk_get_parameter(pubk, 0, &tmp_len);
if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %zu len %zu\n", tmp_len, sizeof(pk_N));
free(tmp);
goto close_pub;
}
free(tmp);
tmp = crypto_pk_get_parameter(pubk, 0, &tmp_len);
if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %zu len %zu\n", tmp_len, sizeof(pk_N));
free(tmp);
goto close_pub;
}
free(tmp);
tmp = crypto_pk_get_parameter(pubk, 1, &tmp_len);
if (tmp_len != sizeof(pk_E) || memcmp(tmp, pk_E, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(1) Exponent.\n");
free(tmp);
goto close_pub;
}
free(tmp);
tmp = crypto_pk_get_parameter(pubk, 1, &tmp_len);
if (tmp_len != sizeof(pk_E) || memcmp(tmp, pk_E, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(1) Exponent.\n");
free(tmp);
goto close_pub;
}
free(tmp);
privk = crypto_pk_open_priv(PK_RSA,
pk_N, sizeof(pk_N),
pk_E, sizeof(pk_E),
pk_D, sizeof(pk_D),
pk_P, sizeof(pk_P),
pk_Q, sizeof(pk_Q),
pk_dP, sizeof(pk_dP),
pk_dQ, sizeof(pk_dQ),
pk_I, sizeof(pk_I));
if (!privk) {
fprintf(stderr, "ERROR: open private key.\n");
goto close_pub;
}
privk = crypto_pk_open_priv(PK_RSA,
pk_N, sizeof(pk_N),
pk_E, sizeof(pk_E),
pk_D, sizeof(pk_D),
pk_P, sizeof(pk_P),
pk_Q, sizeof(pk_Q),
pk_dP, sizeof(pk_dP),
pk_dQ, sizeof(pk_dQ),
pk_I, sizeof(pk_I));
if (!privk) {
fprintf(stderr, "ERROR: open private key.\n");
goto close_pub;
}
tmp_len = crypto_pk_get_nbits(privk);
if (tmp_len != sizeof(pk_N) * 8) {
fprintf(stderr, "ERROR: crypto_pk_get_nbits mismatch.\n");
goto close_pub;
}
tmp_len = crypto_pk_get_nbits(privk);
if (tmp_len != sizeof(pk_N) * 8) {
fprintf(stderr, "ERROR: crypto_pk_get_nbits mismatch.\n");
goto close_pub;
}
tmp = crypto_pk_get_parameter(privk, 0, &tmp_len);
if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %zu len %zu\n", tmp_len, sizeof(pk_N));
free(tmp);
goto close;
}
free(tmp);
tmp = crypto_pk_get_parameter(privk, 0, &tmp_len);
if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %zu len %zu\n", tmp_len, sizeof(pk_N));
free(tmp);
goto close;
}
free(tmp);
tmp = crypto_pk_get_parameter(privk, 1, &tmp_len);
if (tmp_len != sizeof(pk_E) || memcmp(tmp, pk_E, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(1) Exponent.\n");
free(tmp);
goto close;
}
free(tmp);
tmp = crypto_pk_get_parameter(privk, 1, &tmp_len);
if (tmp_len != sizeof(pk_E) || memcmp(tmp, pk_E, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(1) Exponent.\n");
free(tmp);
goto close;
}
free(tmp);
tmp = crypto_pk_decrypt(privk, msg, msg_len, &tmp_len);
if (!tmp) {
fprintf(stderr, "ERROR: crypto_pk_decrypt.\n");
goto close;
}
tmp = crypto_pk_decrypt(privk, msg, msg_len, &tmp_len);
if (!tmp) {
fprintf(stderr, "ERROR: crypto_pk_decrypt.\n");
goto close;
}
tmp2 = crypto_pk_encrypt(pubk, tmp, tmp_len, &tmp2_len);
if (!tmp2) {
fprintf(stderr, "ERROR: crypto_pk_encrypt.\n");
goto free_tmp;
}
tmp2 = crypto_pk_encrypt(pubk, tmp, tmp_len, &tmp2_len);
if (!tmp2) {
fprintf(stderr, "ERROR: crypto_pk_encrypt.\n");
goto free_tmp;
}
if (tmp2_len == msg_len && !memcmp(tmp2, msg, tmp2_len)) {
ret = 0;
} else {
fprintf(stderr, "ERROR: encrypt-decrypt sequence length or data error.\n");
}
if (tmp2_len == msg_len && !memcmp(tmp2, msg, tmp2_len)) {
ret = 0;
} else {
fprintf(stderr, "ERROR: encrypt-decrypt sequence length or data error.\n");
}
free(tmp2);
free(tmp2);
free_tmp:
free(tmp);
free(tmp);
close:
crypto_pk_close(privk);
crypto_pk_close(privk);
close_pub:
crypto_pk_close(pubk);
crypto_pk_close(pubk);
return ret;
return ret;
}
int exec_crypto_test(bool verbose)
{
unsigned int keylengths[] = {1024, 1152, 1408, 1984, 2048, 3072, 4096};
int i;
int ret;
fprintf(stdout, "\n");
unsigned int keylengths[] = {1024, 1152, 1408, 1984, 2048, 3072, 4096};
int i;
int ret;
fprintf(stdout, "\n");
ret = test_pk(verbose);
if (ret) {
fprintf(stderr, "Crypto raw test: failed\n");
return ret;
}
fprintf(stdout, "Crypto raw test: passed\n\n");
ret = test_pk(verbose);
if (ret) {
fprintf(stderr, "Crypto raw test: failed\n");
return ret;
}
fprintf(stdout, "Crypto raw test: passed\n\n");
for (i = 0; i < sizeof(keylengths) / sizeof(keylengths[0]); i++) {
unsigned int kl = keylengths[i];
ret = test_genkey(kl, message, kl / 8, verbose);
if (ret) {
fprintf(stderr, "Crypto generate key[%d] test: failed\n", kl);
return ret;
}
}
for (i = 0; i < sizeof(keylengths) / sizeof(keylengths[0]); i++) {
unsigned int kl = keylengths[i];
ret = test_genkey(kl, message, kl / 8, verbose);
if (ret) {
fprintf(stderr, "Crypto generate key[%d] test: failed\n", kl);
return ret;
}
}
return 0;
return 0;
}

View file

@ -34,73 +34,73 @@
#include "emv/emv_roca.h"
int ExecuteCryptoTests(bool verbose) {
int res;
bool TestFail = false;
int res;
bool TestFail = false;
res = mbedtls_mpi_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_mpi_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_aes_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_aes_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_des_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_des_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_sha1_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_sha1_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_md5_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_md5_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_rsa_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_rsa_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_entropy_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_entropy_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_timing_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_timing_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_ctr_drbg_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_ctr_drbg_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_base64_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_base64_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_cmac_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_cmac_self_test(verbose);
if (res) TestFail = true;
res = ecdsa_nist_test(verbose);
if (res) TestFail = true;
res = ecdsa_nist_test(verbose);
if (res) TestFail = true;
res = mbedtls_ecp_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_ecp_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_x509_self_test(verbose);
if (res) TestFail = true;
res = mbedtls_x509_self_test(verbose);
if (res) TestFail = true;
res = exec_sda_test(verbose);
if (res) TestFail = true;
res = exec_sda_test(verbose);
if (res) TestFail = true;
res = exec_dda_test(verbose);
if (res) TestFail = true;
res = exec_dda_test(verbose);
if (res) TestFail = true;
res = exec_cda_test(verbose);
if (res) TestFail = true;
res = exec_cda_test(verbose);
if (res) TestFail = true;
res = exec_crypto_test(verbose);
if (res) TestFail = true;
res = exec_crypto_test(verbose);
if (res) TestFail = true;
res = roca_self_test();
if (res) TestFail = true;
res = roca_self_test();
if (res) TestFail = true;
PrintAndLog("\n--------------------------");
PrintAndLog("\n--------------------------");
if (TestFail)
PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_(FAIL) );
else
PrintAndLogEx(SUCCESS, "\tTest(s) [ %s ]", _GREEN_(OK) );
if (TestFail)
PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_(FAIL) );
else
PrintAndLogEx(SUCCESS, "\tTest(s) [ %s ]", _GREEN_(OK) );
return TestFail;
return TestFail;
}

View file

@ -30,361 +30,361 @@
#include <stdlib.h>
struct emv_pk mchip_05 = {
.rid = { 0xa0, 0x00, 0x00, 0x00, 0x04, },
.index = 5,
.hash_algo = HASH_SHA_1,
.pk_algo = PK_RSA,
.hash = {
0xeb, 0xfa, 0x0d, 0x5d,
0x06, 0xd8, 0xce, 0x70,
0x2d, 0xa3, 0xea, 0xe8,
0x90, 0x70, 0x1d, 0x45,
0xe2, 0x74, 0xc8, 0x45, },
.exp = { 0x03, },
.elen = 1,
.mlen = 1408 / 8,
.modulus = (unsigned char[]){
0xb8, 0x04, 0x8a, 0xbc, 0x30, 0xc9, 0x0d, 0x97, 0x63, 0x36, 0x54, 0x3e, 0x3f, 0xd7, 0x09, 0x1c,
0x8f, 0xe4, 0x80, 0x0d, 0xf8, 0x20, 0xed, 0x55, 0xe7, 0xe9, 0x48, 0x13, 0xed, 0x00, 0x55, 0x5b,
0x57, 0x3f, 0xec, 0xa3, 0xd8, 0x4a, 0xf6, 0x13, 0x1a, 0x65, 0x1d, 0x66, 0xcf, 0xf4, 0x28, 0x4f,
0xb1, 0x3b, 0x63, 0x5e, 0xdd, 0x0e, 0xe4, 0x01, 0x76, 0xd8, 0xbf, 0x04, 0xb7, 0xfd, 0x1c, 0x7b,
0xac, 0xf9, 0xac, 0x73, 0x27, 0xdf, 0xaa, 0x8a, 0xa7, 0x2d, 0x10, 0xdb, 0x3b, 0x8e, 0x70, 0xb2,
0xdd, 0xd8, 0x11, 0xcb, 0x41, 0x96, 0x52, 0x5e, 0xa3, 0x86, 0xac, 0xc3, 0x3c, 0x0d, 0x9d, 0x45,
0x75, 0x91, 0x64, 0x69, 0xc4, 0xe4, 0xf5, 0x3e, 0x8e, 0x1c, 0x91, 0x2c, 0xc6, 0x18, 0xcb, 0x22,
0xdd, 0xe7, 0xc3, 0x56, 0x8e, 0x90, 0x02, 0x2e, 0x6b, 0xba, 0x77, 0x02, 0x02, 0xe4, 0x52, 0x2a,
0x2d, 0xd6, 0x23, 0xd1, 0x80, 0xe2, 0x15, 0xbd, 0x1d, 0x15, 0x07, 0xfe, 0x3d, 0xc9, 0x0c, 0xa3,
0x10, 0xd2, 0x7b, 0x3e, 0xfc, 0xcd, 0x8f, 0x83, 0xde, 0x30, 0x52, 0xca, 0xd1, 0xe4, 0x89, 0x38,
0xc6, 0x8d, 0x09, 0x5a, 0xac, 0x91, 0xb5, 0xf3, 0x7e, 0x28, 0xbb, 0x49, 0xec, 0x7e, 0xd5, 0x97,
},
.rid = { 0xa0, 0x00, 0x00, 0x00, 0x04, },
.index = 5,
.hash_algo = HASH_SHA_1,
.pk_algo = PK_RSA,
.hash = {
0xeb, 0xfa, 0x0d, 0x5d,
0x06, 0xd8, 0xce, 0x70,
0x2d, 0xa3, 0xea, 0xe8,
0x90, 0x70, 0x1d, 0x45,
0xe2, 0x74, 0xc8, 0x45, },
.exp = { 0x03, },
.elen = 1,
.mlen = 1408 / 8,
.modulus = (unsigned char[]){
0xb8, 0x04, 0x8a, 0xbc, 0x30, 0xc9, 0x0d, 0x97, 0x63, 0x36, 0x54, 0x3e, 0x3f, 0xd7, 0x09, 0x1c,
0x8f, 0xe4, 0x80, 0x0d, 0xf8, 0x20, 0xed, 0x55, 0xe7, 0xe9, 0x48, 0x13, 0xed, 0x00, 0x55, 0x5b,
0x57, 0x3f, 0xec, 0xa3, 0xd8, 0x4a, 0xf6, 0x13, 0x1a, 0x65, 0x1d, 0x66, 0xcf, 0xf4, 0x28, 0x4f,
0xb1, 0x3b, 0x63, 0x5e, 0xdd, 0x0e, 0xe4, 0x01, 0x76, 0xd8, 0xbf, 0x04, 0xb7, 0xfd, 0x1c, 0x7b,
0xac, 0xf9, 0xac, 0x73, 0x27, 0xdf, 0xaa, 0x8a, 0xa7, 0x2d, 0x10, 0xdb, 0x3b, 0x8e, 0x70, 0xb2,
0xdd, 0xd8, 0x11, 0xcb, 0x41, 0x96, 0x52, 0x5e, 0xa3, 0x86, 0xac, 0xc3, 0x3c, 0x0d, 0x9d, 0x45,
0x75, 0x91, 0x64, 0x69, 0xc4, 0xe4, 0xf5, 0x3e, 0x8e, 0x1c, 0x91, 0x2c, 0xc6, 0x18, 0xcb, 0x22,
0xdd, 0xe7, 0xc3, 0x56, 0x8e, 0x90, 0x02, 0x2e, 0x6b, 0xba, 0x77, 0x02, 0x02, 0xe4, 0x52, 0x2a,
0x2d, 0xd6, 0x23, 0xd1, 0x80, 0xe2, 0x15, 0xbd, 0x1d, 0x15, 0x07, 0xfe, 0x3d, 0xc9, 0x0c, 0xa3,
0x10, 0xd2, 0x7b, 0x3e, 0xfc, 0xcd, 0x8f, 0x83, 0xde, 0x30, 0x52, 0xca, 0xd1, 0xe4, 0x89, 0x38,
0xc6, 0x8d, 0x09, 0x5a, 0xac, 0x91, 0xb5, 0xf3, 0x7e, 0x28, 0xbb, 0x49, 0xec, 0x7e, 0xd5, 0x97,
},
};
const unsigned char d_issuer_cert[] = {
0x17, 0x14, 0x28, 0x4f, 0x76, 0x3b, 0x85, 0x86, 0xee, 0x6d, 0x31, 0x99, 0x51, 0xf7, 0xe6, 0x3f,
0xa2, 0x50, 0x76, 0xe5, 0x0d, 0xc9, 0xd3, 0x20, 0x0b, 0xa9, 0x98, 0xd3, 0xa0, 0x52, 0xad, 0xba,
0x9a, 0xb6, 0x9a, 0xc6, 0xad, 0x6a, 0xdd, 0x3c, 0xe0, 0x9f, 0x02, 0x78, 0xf4, 0x07, 0x4e, 0xc4,
0xee, 0x9b, 0x1d, 0x22, 0x68, 0xa3, 0xe9, 0x53, 0x57, 0x5e, 0x45, 0x4e, 0x50, 0xcd, 0x86, 0x0b,
0xf4, 0x24, 0xc5, 0x1c, 0x59, 0x77, 0x12, 0xd2, 0xaa, 0x05, 0x70, 0x89, 0xdd, 0x86, 0x73, 0xe5,
0x1b, 0x1e, 0x1d, 0x71, 0x88, 0x03, 0x48, 0x92, 0x07, 0x7a, 0xc1, 0x8a, 0x6a, 0xe2, 0x34, 0x88,
0xbe, 0xa9, 0xdf, 0x3b, 0x1a, 0x83, 0xf2, 0xc0, 0x80, 0x0c, 0xd7, 0xc5, 0xcd, 0xf2, 0xfd, 0xe0,
0x49, 0x6f, 0x7b, 0xc3, 0x9f, 0xb4, 0xbf, 0x36, 0x32, 0x99, 0xbf, 0xa6, 0x37, 0xb2, 0xec, 0x33,
0xc5, 0x07, 0xe3, 0x68, 0x21, 0xee, 0xc2, 0x07, 0x5f, 0x0e, 0x42, 0x0d, 0x38, 0xa1, 0xc9, 0xf3,
0x12, 0x72, 0x61, 0xba, 0x31, 0x6c, 0x98, 0x76, 0x74, 0xfa, 0xdb, 0x20, 0xea, 0x7f, 0xeb, 0x75,
0xee, 0x45, 0x5d, 0x12, 0x14, 0x6e, 0xa6, 0xf0, 0x2e, 0x8b, 0x01, 0xec, 0x2f, 0xa7, 0xa1, 0x15,
0x17, 0x14, 0x28, 0x4f, 0x76, 0x3b, 0x85, 0x86, 0xee, 0x6d, 0x31, 0x99, 0x51, 0xf7, 0xe6, 0x3f,
0xa2, 0x50, 0x76, 0xe5, 0x0d, 0xc9, 0xd3, 0x20, 0x0b, 0xa9, 0x98, 0xd3, 0xa0, 0x52, 0xad, 0xba,
0x9a, 0xb6, 0x9a, 0xc6, 0xad, 0x6a, 0xdd, 0x3c, 0xe0, 0x9f, 0x02, 0x78, 0xf4, 0x07, 0x4e, 0xc4,
0xee, 0x9b, 0x1d, 0x22, 0x68, 0xa3, 0xe9, 0x53, 0x57, 0x5e, 0x45, 0x4e, 0x50, 0xcd, 0x86, 0x0b,
0xf4, 0x24, 0xc5, 0x1c, 0x59, 0x77, 0x12, 0xd2, 0xaa, 0x05, 0x70, 0x89, 0xdd, 0x86, 0x73, 0xe5,
0x1b, 0x1e, 0x1d, 0x71, 0x88, 0x03, 0x48, 0x92, 0x07, 0x7a, 0xc1, 0x8a, 0x6a, 0xe2, 0x34, 0x88,
0xbe, 0xa9, 0xdf, 0x3b, 0x1a, 0x83, 0xf2, 0xc0, 0x80, 0x0c, 0xd7, 0xc5, 0xcd, 0xf2, 0xfd, 0xe0,
0x49, 0x6f, 0x7b, 0xc3, 0x9f, 0xb4, 0xbf, 0x36, 0x32, 0x99, 0xbf, 0xa6, 0x37, 0xb2, 0xec, 0x33,
0xc5, 0x07, 0xe3, 0x68, 0x21, 0xee, 0xc2, 0x07, 0x5f, 0x0e, 0x42, 0x0d, 0x38, 0xa1, 0xc9, 0xf3,
0x12, 0x72, 0x61, 0xba, 0x31, 0x6c, 0x98, 0x76, 0x74, 0xfa, 0xdb, 0x20, 0xea, 0x7f, 0xeb, 0x75,
0xee, 0x45, 0x5d, 0x12, 0x14, 0x6e, 0xa6, 0xf0, 0x2e, 0x8b, 0x01, 0xec, 0x2f, 0xa7, 0xa1, 0x15,
};
const unsigned char d_issuer_rem[] = {
0x6e, 0x63, 0xb7, 0xbc, 0x70, 0xab, 0xdd, 0x09, 0x34, 0x1b, 0x34, 0xc0, 0x32, 0x86, 0xba, 0x9b,
0xd8, 0x3b, 0xa7, 0x93, 0x6c, 0x5b, 0x77, 0x98, 0xfb, 0x22, 0xc5, 0xe5, 0x3f, 0xf2, 0x40, 0xa2,
0x6d, 0xbd, 0x64, 0x15,
0x6e, 0x63, 0xb7, 0xbc, 0x70, 0xab, 0xdd, 0x09, 0x34, 0x1b, 0x34, 0xc0, 0x32, 0x86, 0xba, 0x9b,
0xd8, 0x3b, 0xa7, 0x93, 0x6c, 0x5b, 0x77, 0x98, 0xfb, 0x22, 0xc5, 0xe5, 0x3f, 0xf2, 0x40, 0xa2,
0x6d, 0xbd, 0x64, 0x15,
};
const unsigned char d_issuer_exp[] = {
0x03,
0x03,
};
const unsigned char d_icc_cert[] = {
0xa4, 0x2f, 0xbe, 0xb1, 0x56, 0xb9, 0x8d, 0xcb, 0x05, 0x54, 0xda, 0x06, 0x2a, 0xdc, 0xa5, 0x30,
0x9a, 0x91, 0xf0, 0x4f, 0xa2, 0xc7, 0xbd, 0x71, 0x02, 0xa8, 0xd7, 0x3f, 0x16, 0xa3, 0xcf, 0xad,
0xe8, 0xaa, 0xdf, 0x4f, 0x3f, 0xe2, 0xa2, 0x12, 0x5c, 0xcd, 0xd7, 0x7c, 0x6b, 0x9f, 0x78, 0xb5,
0xb4, 0x37, 0x1c, 0xe0, 0x80, 0x57, 0x25, 0xb0, 0xf9, 0xc0, 0x27, 0xaf, 0x14, 0x7d, 0x91, 0xe1,
0xff, 0xdb, 0x20, 0x1e, 0x9c, 0x17, 0x0c, 0xe7, 0x77, 0x05, 0x3a, 0x17, 0x2a, 0xd5, 0x26, 0xdc,
0xaf, 0xd3, 0x38, 0x95, 0xe1, 0xa9, 0x47, 0x30, 0x5c, 0x5b, 0x16, 0x7f, 0x2e, 0x7c, 0x6f, 0x99,
0x15, 0x81, 0xa6, 0x52, 0xee, 0x47, 0x31, 0x54, 0x76, 0x0c, 0x2e, 0xd7, 0x74, 0x21, 0x4e, 0x50,
0xdf, 0xec, 0xdd, 0x4c, 0xf2, 0x94, 0xc9, 0x74, 0xb8, 0x9e, 0xbc, 0xa2, 0x5b, 0x5a, 0xb3, 0xc0,
0xbe, 0xb5, 0x0d, 0xfa, 0xf7, 0x82, 0xaf, 0xde, 0x14, 0x33, 0xd9, 0x0c, 0xa2, 0xa8, 0x9d, 0x65,
0x1e, 0x75, 0xd6, 0x7e, 0xbc, 0x7c, 0x3e, 0x36, 0xf5, 0xa1, 0x65, 0xee, 0x61, 0x32, 0x61, 0x29,
0x39, 0xc1, 0xec, 0xd3, 0x99, 0xe4, 0x60, 0x74, 0xb9, 0x96, 0xd9, 0x3a, 0x88, 0xe0, 0x1e, 0x0a,
0xa4, 0x2f, 0xbe, 0xb1, 0x56, 0xb9, 0x8d, 0xcb, 0x05, 0x54, 0xda, 0x06, 0x2a, 0xdc, 0xa5, 0x30,
0x9a, 0x91, 0xf0, 0x4f, 0xa2, 0xc7, 0xbd, 0x71, 0x02, 0xa8, 0xd7, 0x3f, 0x16, 0xa3, 0xcf, 0xad,
0xe8, 0xaa, 0xdf, 0x4f, 0x3f, 0xe2, 0xa2, 0x12, 0x5c, 0xcd, 0xd7, 0x7c, 0x6b, 0x9f, 0x78, 0xb5,
0xb4, 0x37, 0x1c, 0xe0, 0x80, 0x57, 0x25, 0xb0, 0xf9, 0xc0, 0x27, 0xaf, 0x14, 0x7d, 0x91, 0xe1,
0xff, 0xdb, 0x20, 0x1e, 0x9c, 0x17, 0x0c, 0xe7, 0x77, 0x05, 0x3a, 0x17, 0x2a, 0xd5, 0x26, 0xdc,
0xaf, 0xd3, 0x38, 0x95, 0xe1, 0xa9, 0x47, 0x30, 0x5c, 0x5b, 0x16, 0x7f, 0x2e, 0x7c, 0x6f, 0x99,
0x15, 0x81, 0xa6, 0x52, 0xee, 0x47, 0x31, 0x54, 0x76, 0x0c, 0x2e, 0xd7, 0x74, 0x21, 0x4e, 0x50,
0xdf, 0xec, 0xdd, 0x4c, 0xf2, 0x94, 0xc9, 0x74, 0xb8, 0x9e, 0xbc, 0xa2, 0x5b, 0x5a, 0xb3, 0xc0,
0xbe, 0xb5, 0x0d, 0xfa, 0xf7, 0x82, 0xaf, 0xde, 0x14, 0x33, 0xd9, 0x0c, 0xa2, 0xa8, 0x9d, 0x65,
0x1e, 0x75, 0xd6, 0x7e, 0xbc, 0x7c, 0x3e, 0x36, 0xf5, 0xa1, 0x65, 0xee, 0x61, 0x32, 0x61, 0x29,
0x39, 0xc1, 0xec, 0xd3, 0x99, 0xe4, 0x60, 0x74, 0xb9, 0x96, 0xd9, 0x3a, 0x88, 0xe0, 0x1e, 0x0a,
};
const unsigned char d_icc_exp[] = {
0x03,
0x03,
};
const unsigned char d_sdad_cr[] = {
0x3d, 0x87, 0xf3, 0x10, 0x56, 0x10, 0x2d, 0x25, 0x12, 0xcf, 0xde, 0x30, 0x90, 0x06, 0x27, 0xc1,
0x26, 0x3a, 0x76, 0xd1, 0xda, 0xa8, 0x21, 0xf5, 0x08, 0x31, 0xe6, 0x06, 0xc5, 0x45, 0x44, 0xc2,
0x58, 0x13, 0x1e, 0xae, 0xbe, 0x87, 0x4d, 0xcb, 0x1a, 0x28, 0xcf, 0x82, 0xd3, 0xff, 0x91, 0x11,
0x82, 0x60, 0xbc, 0x91, 0x11, 0x37, 0x11, 0xd3, 0xb2, 0x89, 0xfa, 0x41, 0xbe, 0x69, 0xc7, 0xa7,
0xb5, 0xc7, 0x83, 0xe6, 0xf8, 0xf9, 0x7f, 0xce, 0x13, 0xf0, 0x8b, 0x13, 0xfa, 0x44, 0x18, 0x3e,
0x37, 0x18, 0xce, 0xbf, 0x0c, 0x41, 0x47, 0x3d, 0x2b, 0x0f, 0xf4, 0xde, 0x44, 0xb6, 0xa0, 0x2d,
0x75, 0xad, 0xb6, 0xd4, 0x96, 0x23, 0x93, 0xff, 0xdf, 0x4e, 0x69, 0x02, 0x6c, 0xdf, 0x38, 0xff,
0x3d, 0x87, 0xf3, 0x10, 0x56, 0x10, 0x2d, 0x25, 0x12, 0xcf, 0xde, 0x30, 0x90, 0x06, 0x27, 0xc1,
0x26, 0x3a, 0x76, 0xd1, 0xda, 0xa8, 0x21, 0xf5, 0x08, 0x31, 0xe6, 0x06, 0xc5, 0x45, 0x44, 0xc2,
0x58, 0x13, 0x1e, 0xae, 0xbe, 0x87, 0x4d, 0xcb, 0x1a, 0x28, 0xcf, 0x82, 0xd3, 0xff, 0x91, 0x11,
0x82, 0x60, 0xbc, 0x91, 0x11, 0x37, 0x11, 0xd3, 0xb2, 0x89, 0xfa, 0x41, 0xbe, 0x69, 0xc7, 0xa7,
0xb5, 0xc7, 0x83, 0xe6, 0xf8, 0xf9, 0x7f, 0xce, 0x13, 0xf0, 0x8b, 0x13, 0xfa, 0x44, 0x18, 0x3e,
0x37, 0x18, 0xce, 0xbf, 0x0c, 0x41, 0x47, 0x3d, 0x2b, 0x0f, 0xf4, 0xde, 0x44, 0xb6, 0xa0, 0x2d,
0x75, 0xad, 0xb6, 0xd4, 0x96, 0x23, 0x93, 0xff, 0xdf, 0x4e, 0x69, 0x02, 0x6c, 0xdf, 0x38, 0xff,
};
const unsigned char d_ssd1[] = {
0x5f, 0x25, 0x03, 0x14, 0x05, 0x01, 0x5f, 0x24, 0x03, 0x15, 0x06, 0x30, 0x5a, 0x08, 0x52, 0x85,
0x88, 0x12, 0x54, 0x34, 0x56, 0x53, 0x5f, 0x34, 0x01, 0x01, 0x8e, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x1f, 0x03, 0x9f, 0x07, 0x02, 0xff, 0x00, 0x9f, 0x0d, 0x05,
0xbc, 0x50, 0xbc, 0x00, 0x00, 0x9f, 0x0e, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x05,
0xbc, 0x70, 0xbc, 0x98, 0x00, 0x9f, 0x4a, 0x01, 0x82, 0x5f, 0x28, 0x02, 0x06, 0x43, 0x8c, 0x21,
0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03,
0x9c, 0x01, 0x9f, 0x37, 0x04, 0x9f, 0x35, 0x01, 0x9f, 0x45, 0x02, 0x9f, 0x4c, 0x08, 0x9f, 0x34,
0x03, 0x8d, 0x0c, 0x91, 0x0a, 0x8a, 0x02, 0x95, 0x05, 0x9f, 0x37, 0x04, 0x9f, 0x4c, 0x08,
0x39, 0x00,
0x5f, 0x25, 0x03, 0x14, 0x05, 0x01, 0x5f, 0x24, 0x03, 0x15, 0x06, 0x30, 0x5a, 0x08, 0x52, 0x85,
0x88, 0x12, 0x54, 0x34, 0x56, 0x53, 0x5f, 0x34, 0x01, 0x01, 0x8e, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x1f, 0x03, 0x9f, 0x07, 0x02, 0xff, 0x00, 0x9f, 0x0d, 0x05,
0xbc, 0x50, 0xbc, 0x00, 0x00, 0x9f, 0x0e, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x05,
0xbc, 0x70, 0xbc, 0x98, 0x00, 0x9f, 0x4a, 0x01, 0x82, 0x5f, 0x28, 0x02, 0x06, 0x43, 0x8c, 0x21,
0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03,
0x9c, 0x01, 0x9f, 0x37, 0x04, 0x9f, 0x35, 0x01, 0x9f, 0x45, 0x02, 0x9f, 0x4c, 0x08, 0x9f, 0x34,
0x03, 0x8d, 0x0c, 0x91, 0x0a, 0x8a, 0x02, 0x95, 0x05, 0x9f, 0x37, 0x04, 0x9f, 0x4c, 0x08,
0x39, 0x00,
};
static const struct tlv ssd1_tlv = {
.len = sizeof(d_ssd1),
.value = d_ssd1,
.len = sizeof(d_ssd1),
.value = d_ssd1,
};
const unsigned char d_pan[] = {
0x52, 0x85, 0x88, 0x12, 0x54, 0x34, 0x56, 0x53,
0x52, 0x85, 0x88, 0x12, 0x54, 0x34, 0x56, 0x53,
};
const unsigned char d_dd1[] = {
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
static const struct tlv dd1_tlv = {
.len = sizeof(d_dd1),
.value = d_dd1,
.len = sizeof(d_dd1),
.value = d_dd1,
};
static int dda_test_raw(bool verbose)
{
const struct emv_pk *pk = &mchip_05;
const struct emv_pk *pk = &mchip_05;
struct crypto_pk *kcp = crypto_pk_open(PK_RSA,
pk->modulus, pk->mlen,
pk->exp, pk->elen);
if (!kcp)
return 1;
struct crypto_pk *kcp = crypto_pk_open(PK_RSA,
pk->modulus, pk->mlen,
pk->exp, pk->elen);
if (!kcp)
return 1;
unsigned char *ipk_data;
size_t ipk_data_len;
ipk_data = crypto_pk_encrypt(kcp, d_issuer_cert, sizeof(d_issuer_cert), &ipk_data_len);
crypto_pk_close(kcp);
unsigned char *ipk_data;
size_t ipk_data_len;
ipk_data = crypto_pk_encrypt(kcp, d_issuer_cert, sizeof(d_issuer_cert), &ipk_data_len);
crypto_pk_close(kcp);
if (!ipk_data)
return 1;
if (!ipk_data)
return 1;
if (verbose) {
printf("issuer cert:\n");
dump_buffer(ipk_data, ipk_data_len, stdout, 0);
}
if (verbose) {
printf("issuer cert:\n");
dump_buffer(ipk_data, ipk_data_len, stdout, 0);
}
size_t ipk_pk_len = ipk_data[13];
unsigned char *ipk_pk = malloc(ipk_pk_len);
memcpy(ipk_pk, ipk_data + 15, ipk_data_len - 36);
memcpy(ipk_pk + ipk_data_len - 36, d_issuer_rem, sizeof(d_issuer_rem));
size_t ipk_pk_len = ipk_data[13];
unsigned char *ipk_pk = malloc(ipk_pk_len);
memcpy(ipk_pk, ipk_data + 15, ipk_data_len - 36);
memcpy(ipk_pk + ipk_data_len - 36, d_issuer_rem, sizeof(d_issuer_rem));
struct crypto_hash *ch;
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(ipk_pk);
free(ipk_data);
return 1;
}
struct crypto_hash *ch;
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(ipk_pk);
free(ipk_data);
return 1;
}
crypto_hash_write(ch, ipk_data + 1, 14);
crypto_hash_write(ch, ipk_pk, ipk_pk_len);
crypto_hash_write(ch, d_issuer_exp, sizeof(d_issuer_exp));
crypto_hash_write(ch, ipk_data + 1, 14);
crypto_hash_write(ch, ipk_pk, ipk_pk_len);
crypto_hash_write(ch, d_issuer_exp, sizeof(d_issuer_exp));
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
if (verbose) {
printf("crypto hash:\n");
dump_buffer(h, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash:\n");
dump_buffer(h, 20, stdout, 0);
}
if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
crypto_hash_close(ch);
free(ipk_data);
crypto_hash_close(ch);
free(ipk_data);
struct crypto_pk *ikcp = crypto_pk_open(PK_RSA, ipk_pk, (int) ipk_pk_len,
d_issuer_exp, (int) sizeof(d_issuer_exp));
free(ipk_pk);
if (!ikcp)
return 1;
struct crypto_pk *ikcp = crypto_pk_open(PK_RSA, ipk_pk, (int) ipk_pk_len,
d_issuer_exp, (int) sizeof(d_issuer_exp));
free(ipk_pk);
if (!ikcp)
return 1;
unsigned char *iccpk_data;
size_t iccpk_data_len;
iccpk_data = crypto_pk_encrypt(ikcp, d_icc_cert, sizeof(d_icc_cert), &iccpk_data_len);
crypto_pk_close(ikcp);
unsigned char *iccpk_data;
size_t iccpk_data_len;
iccpk_data = crypto_pk_encrypt(ikcp, d_icc_cert, sizeof(d_icc_cert), &iccpk_data_len);
crypto_pk_close(ikcp);
if (!iccpk_data)
return 1;
if (!iccpk_data)
return 1;
if (verbose) {
printf("icc cert:\n");
dump_buffer(iccpk_data, iccpk_data_len, stdout, 0);
}
if (verbose) {
printf("icc cert:\n");
dump_buffer(iccpk_data, iccpk_data_len, stdout, 0);
}
size_t iccpk_pk_len = iccpk_data[19];
unsigned char *iccpk_pk = malloc(iccpk_pk_len);
memcpy(iccpk_pk, iccpk_data + 21, /*iccpk_data_len - 36*/iccpk_pk_len);
/*memcpy(iccpk_pk + iccpk_data_len - 36, icc_rem, sizeof(icc_rem));*/
size_t iccpk_pk_len = iccpk_data[19];
unsigned char *iccpk_pk = malloc(iccpk_pk_len);
memcpy(iccpk_pk, iccpk_data + 21, /*iccpk_data_len - 36*/iccpk_pk_len);
/*memcpy(iccpk_pk + iccpk_data_len - 36, icc_rem, sizeof(icc_rem));*/
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(iccpk_pk);
free(iccpk_data);
return 1;
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(iccpk_pk);
free(iccpk_data);
return 1;
}
crypto_hash_write(ch, iccpk_data + 1, iccpk_data_len - 22);
crypto_hash_write(ch, d_icc_exp, sizeof(d_icc_exp));
crypto_hash_write(ch, d_ssd1, sizeof(d_ssd1));
crypto_hash_write(ch, iccpk_data + 1, iccpk_data_len - 22);
crypto_hash_write(ch, d_icc_exp, sizeof(d_icc_exp));
crypto_hash_write(ch, d_ssd1, sizeof(d_ssd1));
h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(iccpk_pk);
free(iccpk_data);
return 1;
}
h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(iccpk_pk);
free(iccpk_data);
return 1;
}
if (verbose) {
printf("crypto hash1.1:\n");
dump_buffer(h, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash1.1:\n");
dump_buffer(h, 20, stdout, 0);
}
if (memcmp(iccpk_data + iccpk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(iccpk_pk);
free(iccpk_data);
return 1;
}
if (memcmp(iccpk_data + iccpk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(iccpk_pk);
free(iccpk_data);
return 1;
}
crypto_hash_close(ch);
free(iccpk_data);
crypto_hash_close(ch);
free(iccpk_data);
struct crypto_pk *icckcp = crypto_pk_open(PK_RSA, iccpk_pk, (int) iccpk_pk_len,
d_issuer_exp, (int) sizeof(d_issuer_exp));
free(iccpk_pk);
if (!icckcp)
return 1;
struct crypto_pk *icckcp = crypto_pk_open(PK_RSA, iccpk_pk, (int) iccpk_pk_len,
d_issuer_exp, (int) sizeof(d_issuer_exp));
free(iccpk_pk);
if (!icckcp)
return 1;
size_t sdad_len;
unsigned char *sdad = crypto_pk_encrypt(icckcp, d_sdad_cr, sizeof(d_sdad_cr), &sdad_len);
crypto_pk_close(icckcp);
if (!sdad)
return 1;
size_t sdad_len;
unsigned char *sdad = crypto_pk_encrypt(icckcp, d_sdad_cr, sizeof(d_sdad_cr), &sdad_len);
crypto_pk_close(icckcp);
if (!sdad)
return 1;
if (verbose) {
printf("sdad:\n");
dump_buffer(sdad, sdad_len, stdout, 0);
}
if (verbose) {
printf("sdad:\n");
dump_buffer(sdad, sdad_len, stdout, 0);
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(sdad);
return 1;
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(sdad);
return 1;
}
crypto_hash_write(ch, sdad + 1, sdad_len - 22);
crypto_hash_write(ch, d_dd1, sizeof(d_dd1));
crypto_hash_write(ch, sdad + 1, sdad_len - 22);
crypto_hash_write(ch, d_dd1, sizeof(d_dd1));
unsigned char *h2 = crypto_hash_read(ch);
if (!h2) {
crypto_hash_close(ch);
free(sdad);
return 1;
}
unsigned char *h2 = crypto_hash_read(ch);
if (!h2) {
crypto_hash_close(ch);
free(sdad);
return 1;
}
if (verbose) {
printf("crypto hash2:\n");
dump_buffer(h2, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash2:\n");
dump_buffer(h2, 20, stdout, 0);
}
crypto_hash_close(ch);
crypto_hash_close(ch);
free(sdad);
free(sdad);
return 0;
return 0;
}
static int dda_test_pk(bool verbose)
{
const struct emv_pk *pk = &mchip_05;
struct tlvdb *db;
const struct emv_pk *pk = &mchip_05;
struct tlvdb *db;
db = tlvdb_external(0x90, sizeof(d_issuer_cert), d_issuer_cert);
tlvdb_add(db, tlvdb_external(0x9f32, sizeof(d_issuer_exp), d_issuer_exp));
tlvdb_add(db, tlvdb_external(0x92, sizeof(d_issuer_rem), d_issuer_rem));
tlvdb_add(db, tlvdb_external(0x5a, sizeof(d_pan), d_pan));
db = tlvdb_external(0x90, sizeof(d_issuer_cert), d_issuer_cert);
tlvdb_add(db, tlvdb_external(0x9f32, sizeof(d_issuer_exp), d_issuer_exp));
tlvdb_add(db, tlvdb_external(0x92, sizeof(d_issuer_rem), d_issuer_rem));
tlvdb_add(db, tlvdb_external(0x5a, sizeof(d_pan), d_pan));
struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
if (!ipk) {
fprintf(stderr, "Could not recover Issuer certificate!\n");
tlvdb_free(db);
return 2;
}
struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
if (!ipk) {
fprintf(stderr, "Could not recover Issuer certificate!\n");
tlvdb_free(db);
return 2;
}
tlvdb_add(db, tlvdb_external(0x9f46, sizeof(d_icc_cert), d_icc_cert));
tlvdb_add(db, tlvdb_external(0x9f47, sizeof(d_icc_exp), d_icc_exp));
/*tlvdb_add(db, tlvdb_external(0x9f48, sizeof(d_issuer_rem), d_issuer_rem));*/
tlvdb_add(db, tlvdb_external(0x9f46, sizeof(d_icc_cert), d_icc_cert));
tlvdb_add(db, tlvdb_external(0x9f47, sizeof(d_icc_exp), d_icc_exp));
/*tlvdb_add(db, tlvdb_external(0x9f48, sizeof(d_issuer_rem), d_issuer_rem));*/
struct emv_pk *iccpk = emv_pki_recover_icc_cert(ipk, db, &ssd1_tlv);
if (!iccpk) {
fprintf(stderr, "Could not recover ICC certificate!\n");
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
struct emv_pk *iccpk = emv_pki_recover_icc_cert(ipk, db, &ssd1_tlv);
if (!iccpk) {
fprintf(stderr, "Could not recover ICC certificate!\n");
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
tlvdb_add(db, tlvdb_external(0x9f4b, sizeof(d_sdad_cr), d_sdad_cr));
tlvdb_add(db, tlvdb_external(0x9f4b, sizeof(d_sdad_cr), d_sdad_cr));
struct tlvdb *idndb = emv_pki_recover_idn(iccpk, db, &dd1_tlv);
if (!idndb) {
fprintf(stderr, "Could not recover IDN!\n");
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
struct tlvdb *idndb = emv_pki_recover_idn(iccpk, db, &dd1_tlv);
if (!idndb) {
fprintf(stderr, "Could not recover IDN!\n");
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
const struct tlv *idn = tlvdb_get(idndb, 0x9f4c, NULL);
if (!idn) {
fprintf(stderr, "IDN not found!\n");
tlvdb_free(idndb);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
const struct tlv *idn = tlvdb_get(idndb, 0x9f4c, NULL);
if (!idn) {
fprintf(stderr, "IDN not found!\n");
tlvdb_free(idndb);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
if (verbose) {
printf("IDN:\n");
dump_buffer(idn->value, idn->len, stdout, 0);
}
if (verbose) {
printf("IDN:\n");
dump_buffer(idn->value, idn->len, stdout, 0);
}
tlvdb_free(idndb);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
tlvdb_free(idndb);
emv_pk_free(iccpk);
emv_pk_free(ipk);
tlvdb_free(db);
return 0;
return 0;
}
int exec_dda_test(bool verbose)
{
int ret;
fprintf(stdout, "\n");
int ret;
fprintf(stdout, "\n");
ret = dda_test_raw(verbose);
if (ret) {
fprintf(stderr, "DDA raw test: failed\n");
return ret;
}
fprintf(stdout, "DDA raw test: passed\n");
ret = dda_test_raw(verbose);
if (ret) {
fprintf(stderr, "DDA raw test: failed\n");
return ret;
}
fprintf(stdout, "DDA raw test: passed\n");
ret = dda_test_pk(verbose);
if (ret) {
fprintf(stderr, "DDA test pk: failed\n");
return ret;
}
fprintf(stdout, "DDA test pk: passed\n");
ret = dda_test_pk(verbose);
if (ret) {
fprintf(stderr, "DDA test pk: failed\n");
return ret;
}
fprintf(stdout, "DDA test pk: passed\n");
return 0;
return 0;
}

View file

@ -28,250 +28,250 @@
#include <stdlib.h>
struct emv_pk vsdc_01 = {
.rid = { 0xa0, 0x00, 0x00, 0x00, 0x03, },
.index = 1,
.hash_algo = HASH_SHA_1,
.pk_algo = PK_RSA,
.hash = {
0xd3, 0x4a, 0x6a, 0x77,
0x60, 0x11, 0xc7, 0xe7,
0xce, 0x3a, 0xec, 0x5f,
0x03, 0xad, 0x2f, 0x8c,
0xfc, 0x55, 0x03, 0xcc, },
.exp = { 0x03, },
.elen = 1,
.mlen = 1024 / 8,
.modulus = (unsigned char[]){
0xc6, 0x96, 0x03, 0x42, 0x13, 0xd7, 0xd8, 0x54, 0x69, 0x84, 0x57, 0x9d, 0x1d, 0x0f, 0x0e, 0xa5,
0x19, 0xcf, 0xf8, 0xde, 0xff, 0xc4, 0x29, 0x35, 0x4c, 0xf3, 0xa8, 0x71, 0xa6, 0xf7, 0x18, 0x3f,
0x12, 0x28, 0xda, 0x5c, 0x74, 0x70, 0xc0, 0x55, 0x38, 0x71, 0x00, 0xcb, 0x93, 0x5a, 0x71, 0x2c,
0x4e, 0x28, 0x64, 0xdf, 0x5d, 0x64, 0xba, 0x93, 0xfe, 0x7e, 0x63, 0xe7, 0x1f, 0x25, 0xb1, 0xe5,
0xf5, 0x29, 0x85, 0x75, 0xeb, 0xe1, 0xc6, 0x3a, 0xa6, 0x17, 0x70, 0x69, 0x17, 0x91, 0x1d, 0xc2,
0xa7, 0x5a, 0xc2, 0x8b, 0x25, 0x1c, 0x7e, 0xf4, 0x0f, 0x23, 0x65, 0x91, 0x24, 0x90, 0xb9, 0x39,
0xbc, 0xa2, 0x12, 0x4a, 0x30, 0xa2, 0x8f, 0x54, 0x40, 0x2c, 0x34, 0xae, 0xca, 0x33, 0x1a, 0xb6,
0x7e, 0x1e, 0x79, 0xb2, 0x85, 0xdd, 0x57, 0x71, 0xb5, 0xd9, 0xff, 0x79, 0xea, 0x63, 0x0b, 0x75,
},
.rid = { 0xa0, 0x00, 0x00, 0x00, 0x03, },
.index = 1,
.hash_algo = HASH_SHA_1,
.pk_algo = PK_RSA,
.hash = {
0xd3, 0x4a, 0x6a, 0x77,
0x60, 0x11, 0xc7, 0xe7,
0xce, 0x3a, 0xec, 0x5f,
0x03, 0xad, 0x2f, 0x8c,
0xfc, 0x55, 0x03, 0xcc, },
.exp = { 0x03, },
.elen = 1,
.mlen = 1024 / 8,
.modulus = (unsigned char[]){
0xc6, 0x96, 0x03, 0x42, 0x13, 0xd7, 0xd8, 0x54, 0x69, 0x84, 0x57, 0x9d, 0x1d, 0x0f, 0x0e, 0xa5,
0x19, 0xcf, 0xf8, 0xde, 0xff, 0xc4, 0x29, 0x35, 0x4c, 0xf3, 0xa8, 0x71, 0xa6, 0xf7, 0x18, 0x3f,
0x12, 0x28, 0xda, 0x5c, 0x74, 0x70, 0xc0, 0x55, 0x38, 0x71, 0x00, 0xcb, 0x93, 0x5a, 0x71, 0x2c,
0x4e, 0x28, 0x64, 0xdf, 0x5d, 0x64, 0xba, 0x93, 0xfe, 0x7e, 0x63, 0xe7, 0x1f, 0x25, 0xb1, 0xe5,
0xf5, 0x29, 0x85, 0x75, 0xeb, 0xe1, 0xc6, 0x3a, 0xa6, 0x17, 0x70, 0x69, 0x17, 0x91, 0x1d, 0xc2,
0xa7, 0x5a, 0xc2, 0x8b, 0x25, 0x1c, 0x7e, 0xf4, 0x0f, 0x23, 0x65, 0x91, 0x24, 0x90, 0xb9, 0x39,
0xbc, 0xa2, 0x12, 0x4a, 0x30, 0xa2, 0x8f, 0x54, 0x40, 0x2c, 0x34, 0xae, 0xca, 0x33, 0x1a, 0xb6,
0x7e, 0x1e, 0x79, 0xb2, 0x85, 0xdd, 0x57, 0x71, 0xb5, 0xd9, 0xff, 0x79, 0xea, 0x63, 0x0b, 0x75,
},
};
const unsigned char issuer_cert[] = {
0x3c, 0x5f, 0xea, 0xd4, 0xdd, 0x7b, 0xca, 0x44, 0xf9, 0x3e, 0x90, 0xc4, 0x4f, 0x76, 0xed, 0xe5,
0x4a, 0x32, 0x88, 0xec, 0xdc, 0x78, 0x46, 0x9f, 0xcb, 0x12, 0x25, 0xc0, 0x3b, 0x2c, 0x04, 0xf2,
0xc2, 0xf4, 0x12, 0x28, 0x1a, 0x08, 0x22, 0xdf, 0x14, 0x64, 0x92, 0x30, 0x98, 0x9f, 0xb1, 0x49,
0x40, 0x70, 0xda, 0xf8, 0xc9, 0x53, 0x4a, 0x78, 0x81, 0x96, 0x01, 0x48, 0x61, 0x6a, 0xce, 0x58,
0x17, 0x88, 0x12, 0x0d, 0x35, 0x06, 0xac, 0xe4, 0xce, 0xe5, 0x64, 0xfb, 0x27, 0xee, 0x53, 0x34,
0x1c, 0x22, 0xf0, 0xb4, 0x5b, 0x31, 0x87, 0x3d, 0x05, 0xde, 0x54, 0x5e, 0xfe, 0x33, 0xbc, 0xd2,
0x9b, 0x21, 0x85, 0xd0, 0x35, 0xa8, 0x06, 0xad, 0x08, 0xc6, 0x97, 0x6f, 0x35, 0x05, 0xa1, 0x99,
0x99, 0x93, 0x0c, 0xa8, 0xa0, 0x3e, 0xfa, 0x32, 0x1c, 0x48, 0x60, 0x61, 0xf7, 0xdc, 0xec, 0x9f,
0x3c, 0x5f, 0xea, 0xd4, 0xdd, 0x7b, 0xca, 0x44, 0xf9, 0x3e, 0x90, 0xc4, 0x4f, 0x76, 0xed, 0xe5,
0x4a, 0x32, 0x88, 0xec, 0xdc, 0x78, 0x46, 0x9f, 0xcb, 0x12, 0x25, 0xc0, 0x3b, 0x2c, 0x04, 0xf2,
0xc2, 0xf4, 0x12, 0x28, 0x1a, 0x08, 0x22, 0xdf, 0x14, 0x64, 0x92, 0x30, 0x98, 0x9f, 0xb1, 0x49,
0x40, 0x70, 0xda, 0xf8, 0xc9, 0x53, 0x4a, 0x78, 0x81, 0x96, 0x01, 0x48, 0x61, 0x6a, 0xce, 0x58,
0x17, 0x88, 0x12, 0x0d, 0x35, 0x06, 0xac, 0xe4, 0xce, 0xe5, 0x64, 0xfb, 0x27, 0xee, 0x53, 0x34,
0x1c, 0x22, 0xf0, 0xb4, 0x5b, 0x31, 0x87, 0x3d, 0x05, 0xde, 0x54, 0x5e, 0xfe, 0x33, 0xbc, 0xd2,
0x9b, 0x21, 0x85, 0xd0, 0x35, 0xa8, 0x06, 0xad, 0x08, 0xc6, 0x97, 0x6f, 0x35, 0x05, 0xa1, 0x99,
0x99, 0x93, 0x0c, 0xa8, 0xa0, 0x3e, 0xfa, 0x32, 0x1c, 0x48, 0x60, 0x61, 0xf7, 0xdc, 0xec, 0x9f,
};
const unsigned char issuer_rem[] = {
0x1e, 0xbc, 0xa3, 0x0f, 0x00, 0xce, 0x59, 0x62, 0xa8, 0xc6, 0xe1, 0x30, 0x54, 0x4b, 0x82, 0x89,
0x1b, 0x23, 0x6c, 0x65, 0xde, 0x29, 0x31, 0x7f, 0x36, 0x47, 0x35, 0xde, 0xe6, 0x3f, 0x65, 0x98,
0x97, 0x58, 0x35, 0xd5
0x1e, 0xbc, 0xa3, 0x0f, 0x00, 0xce, 0x59, 0x62, 0xa8, 0xc6, 0xe1, 0x30, 0x54, 0x4b, 0x82, 0x89,
0x1b, 0x23, 0x6c, 0x65, 0xde, 0x29, 0x31, 0x7f, 0x36, 0x47, 0x35, 0xde, 0xe6, 0x3f, 0x65, 0x98,
0x97, 0x58, 0x35, 0xd5
};
const unsigned char issuer_exp[] = {
0x03,
0x03,
};
const unsigned char ssad_cr[] = {
0x99, 0xa5, 0x58, 0xb6, 0x2b, 0x67, 0x4a, 0xa5, 0xe7, 0xd2, 0xa5, 0x7e, 0x5e, 0xf6, 0xa6, 0xf2,
0x25, 0x8e, 0x5d, 0xa0, 0x52, 0xd0, 0x5b, 0x54, 0xe5, 0xc1, 0x15, 0xff, 0x1c, 0xec, 0xf9, 0x4a,
0xa2, 0xdf, 0x8f, 0x39, 0xa0, 0x1d, 0x71, 0xc6, 0x19, 0xeb, 0x81, 0x9d, 0xa5, 0x2e, 0xf3, 0x81,
0xe8, 0x49, 0x79, 0x58, 0x6a, 0xea, 0x78, 0x55, 0xff, 0xbe, 0xf4, 0x0a, 0xa3, 0xa7, 0x1c, 0xd3,
0xb0, 0x4c, 0xfd, 0xf2, 0x70, 0xae, 0xc8, 0x15, 0x8a, 0x27, 0x97, 0xf2, 0x4f, 0xd6, 0x13, 0xb7,
0x48, 0x13, 0x46, 0x61, 0x13, 0x5c, 0xd2, 0x90, 0xe4, 0x5b, 0x04, 0xa8, 0xe0, 0xcc, 0xc7, 0x11,
0xae, 0x04, 0x2f, 0x15, 0x9e, 0x73, 0xc8, 0x9c, 0x2a, 0x7e, 0x65, 0xa4, 0xc2, 0xfd, 0x1d, 0x61,
0x06, 0x02, 0x4a, 0xa2, 0x71, 0x30, 0xb0, 0xec, 0xec, 0x02, 0x38, 0xf9, 0x16, 0x59, 0xde, 0x96,
0x99, 0xa5, 0x58, 0xb6, 0x2b, 0x67, 0x4a, 0xa5, 0xe7, 0xd2, 0xa5, 0x7e, 0x5e, 0xf6, 0xa6, 0xf2,
0x25, 0x8e, 0x5d, 0xa0, 0x52, 0xd0, 0x5b, 0x54, 0xe5, 0xc1, 0x15, 0xff, 0x1c, 0xec, 0xf9, 0x4a,
0xa2, 0xdf, 0x8f, 0x39, 0xa0, 0x1d, 0x71, 0xc6, 0x19, 0xeb, 0x81, 0x9d, 0xa5, 0x2e, 0xf3, 0x81,
0xe8, 0x49, 0x79, 0x58, 0x6a, 0xea, 0x78, 0x55, 0xff, 0xbe, 0xf4, 0x0a, 0xa3, 0xa7, 0x1c, 0xd3,
0xb0, 0x4c, 0xfd, 0xf2, 0x70, 0xae, 0xc8, 0x15, 0x8a, 0x27, 0x97, 0xf2, 0x4f, 0xd6, 0x13, 0xb7,
0x48, 0x13, 0x46, 0x61, 0x13, 0x5c, 0xd2, 0x90, 0xe4, 0x5b, 0x04, 0xa8, 0xe0, 0xcc, 0xc7, 0x11,
0xae, 0x04, 0x2f, 0x15, 0x9e, 0x73, 0xc8, 0x9c, 0x2a, 0x7e, 0x65, 0xa4, 0xc2, 0xfd, 0x1d, 0x61,
0x06, 0x02, 0x4a, 0xa2, 0x71, 0x30, 0xb0, 0xec, 0xec, 0x02, 0x38, 0xf9, 0x16, 0x59, 0xde, 0x96,
};
const unsigned char ssd1[] = {
0x5f, 0x24, 0x03, 0x08, 0x12, 0x31, 0x5a, 0x08, 0x42, 0x76, 0x55, 0x00, 0x13, 0x23, 0x45, 0x99, 0x5f, 0x34, 0x01, 0x01, 0x9f, 0x07, 0x02, 0xff, 0x00, 0x9f, 0x0d, 0x05, 0xd0, 0x40, 0xac, 0xa8, 0x00, 0x9f, 0x0e, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x05, 0xd0, 0x68, 0xbc, 0xf8, 0x00,
0x5c, 0x00,
0x5f, 0x24, 0x03, 0x08, 0x12, 0x31, 0x5a, 0x08, 0x42, 0x76, 0x55, 0x00, 0x13, 0x23, 0x45, 0x99, 0x5f, 0x34, 0x01, 0x01, 0x9f, 0x07, 0x02, 0xff, 0x00, 0x9f, 0x0d, 0x05, 0xd0, 0x40, 0xac, 0xa8, 0x00, 0x9f, 0x0e, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x05, 0xd0, 0x68, 0xbc, 0xf8, 0x00,
0x5c, 0x00,
};
static const struct tlv ssd1_tlv = {
.len = sizeof(ssd1),
.value = ssd1,
.len = sizeof(ssd1),
.value = ssd1,
};
const unsigned char pan[] = {
0x42, 0x76, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
0x42, 0x76, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static int sda_test_raw(bool verbose)
{
const struct emv_pk *pk = &vsdc_01;
const struct emv_pk *pk = &vsdc_01;
struct crypto_pk *kcp = crypto_pk_open(PK_RSA,
pk->modulus, pk->mlen,
pk->exp, pk->elen);
if (!kcp)
return 1;
struct crypto_pk *kcp = crypto_pk_open(PK_RSA,
pk->modulus, pk->mlen,
pk->exp, pk->elen);
if (!kcp)
return 1;
unsigned char *ipk_data;
size_t ipk_data_len;
ipk_data = crypto_pk_encrypt(kcp, issuer_cert, sizeof(issuer_cert), &ipk_data_len);
crypto_pk_close(kcp);
unsigned char *ipk_data;
size_t ipk_data_len;
ipk_data = crypto_pk_encrypt(kcp, issuer_cert, sizeof(issuer_cert), &ipk_data_len);
crypto_pk_close(kcp);
if (!ipk_data)
return 1;
if (!ipk_data)
return 1;
if (verbose) {
printf("issuer cert:\n");
dump_buffer(ipk_data, ipk_data_len, stdout, 0);
}
if (verbose) {
printf("issuer cert:\n");
dump_buffer(ipk_data, ipk_data_len, stdout, 0);
}
size_t ipk_pk_len = ipk_data[13];
unsigned char *ipk_pk = malloc(ipk_pk_len);
memcpy(ipk_pk, ipk_data + 15, ipk_data_len - 36);
memcpy(ipk_pk + ipk_data_len - 36, issuer_rem, sizeof(issuer_rem));
size_t ipk_pk_len = ipk_data[13];
unsigned char *ipk_pk = malloc(ipk_pk_len);
memcpy(ipk_pk, ipk_data + 15, ipk_data_len - 36);
memcpy(ipk_pk + ipk_data_len - 36, issuer_rem, sizeof(issuer_rem));
struct crypto_hash *ch;
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(ipk_pk);
free(ipk_data);
return 1;
}
struct crypto_hash *ch;
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(ipk_pk);
free(ipk_data);
return 1;
}
crypto_hash_write(ch, ipk_data + 1, 14);
crypto_hash_write(ch, ipk_pk, ipk_pk_len);
crypto_hash_write(ch, issuer_exp, sizeof(issuer_exp));
crypto_hash_write(ch, ipk_data + 1, 14);
crypto_hash_write(ch, ipk_pk, ipk_pk_len);
crypto_hash_write(ch, issuer_exp, sizeof(issuer_exp));
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
unsigned char *h = crypto_hash_read(ch);
if (!h) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
if (verbose) {
printf("crypto hash:\n");
dump_buffer(h, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash:\n");
dump_buffer(h, 20, stdout, 0);
}
if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) {
crypto_hash_close(ch);
free(ipk_pk);
free(ipk_data);
return 1;
}
crypto_hash_close(ch);
free(ipk_data);
crypto_hash_close(ch);
free(ipk_data);
struct crypto_pk *ikcp = crypto_pk_open(PK_RSA, ipk_pk, (int) ipk_pk_len,
issuer_exp, (int) sizeof(issuer_exp));
free(ipk_pk);
if (!ikcp)
return 1;
struct crypto_pk *ikcp = crypto_pk_open(PK_RSA, ipk_pk, (int) ipk_pk_len,
issuer_exp, (int) sizeof(issuer_exp));
free(ipk_pk);
if (!ikcp)
return 1;
size_t ssad_len;
unsigned char *ssad = crypto_pk_encrypt(ikcp, ssad_cr, sizeof(ssad_cr), &ssad_len);
crypto_pk_close(ikcp);
if (!ssad)
return 1;
size_t ssad_len;
unsigned char *ssad = crypto_pk_encrypt(ikcp, ssad_cr, sizeof(ssad_cr), &ssad_len);
crypto_pk_close(ikcp);
if (!ssad)
return 1;
if (verbose) {
printf("ssad:\n");
dump_buffer(ssad, ssad_len, stdout, 0);
}
if (verbose) {
printf("ssad:\n");
dump_buffer(ssad, ssad_len, stdout, 0);
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(ssad);
return 1;
}
ch = crypto_hash_open(HASH_SHA_1);
if (!ch) {
free(ssad);
return 1;
}
crypto_hash_write(ch, ssad + 1, ssad_len - 22);
crypto_hash_write(ch, ssd1, sizeof(ssd1));
crypto_hash_write(ch, ssad + 1, ssad_len - 22);
crypto_hash_write(ch, ssd1, sizeof(ssd1));
unsigned char *h2 = crypto_hash_read(ch);
if (!h2) {
crypto_hash_close(ch);
free(ssad);
return 1;
}
unsigned char *h2 = crypto_hash_read(ch);
if (!h2) {
crypto_hash_close(ch);
free(ssad);
return 1;
}
if (verbose) {
printf("crypto hash2:\n");
dump_buffer(h2, 20, stdout, 0);
}
if (verbose) {
printf("crypto hash2:\n");
dump_buffer(h2, 20, stdout, 0);
}
crypto_hash_close(ch);
crypto_hash_close(ch);
free(ssad);
free(ssad);
return 0;
return 0;
}
static int sda_test_pk(bool verbose)
{
const struct emv_pk *pk = &vsdc_01;
struct tlvdb *db;
const struct emv_pk *pk = &vsdc_01;
struct tlvdb *db;
db = tlvdb_external(0x90, sizeof(issuer_cert), issuer_cert);
tlvdb_add(db, tlvdb_external(0x9f32, sizeof(issuer_exp), issuer_exp));
tlvdb_add(db, tlvdb_external(0x92, sizeof(issuer_rem), issuer_rem));
tlvdb_add(db, tlvdb_external(0x5a, sizeof(pan), pan));
db = tlvdb_external(0x90, sizeof(issuer_cert), issuer_cert);
tlvdb_add(db, tlvdb_external(0x9f32, sizeof(issuer_exp), issuer_exp));
tlvdb_add(db, tlvdb_external(0x92, sizeof(issuer_rem), issuer_rem));
tlvdb_add(db, tlvdb_external(0x5a, sizeof(pan), pan));
struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
if (!ipk) {
fprintf(stderr, "Could not recover Issuer certificate!\n");
tlvdb_free(db);
return 2;
}
struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
if (!ipk) {
fprintf(stderr, "Could not recover Issuer certificate!\n");
tlvdb_free(db);
return 2;
}
tlvdb_add(db, tlvdb_external(0x93, sizeof(ssad_cr), ssad_cr));
tlvdb_add(db, tlvdb_external(0x93, sizeof(ssad_cr), ssad_cr));
struct tlvdb *dacdb = emv_pki_recover_dac(ipk, db, &ssd1_tlv);
if (!dacdb) {
fprintf(stderr, "Could not recover DAC!\n");
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
struct tlvdb *dacdb = emv_pki_recover_dac(ipk, db, &ssd1_tlv);
if (!dacdb) {
fprintf(stderr, "Could not recover DAC!\n");
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
const struct tlv *dac = tlvdb_get(dacdb, 0x9f45, NULL);
if (!dac) {
fprintf(stderr, "DAC not found!\n");
tlvdb_free(dacdb);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
const struct tlv *dac = tlvdb_get(dacdb, 0x9f45, NULL);
if (!dac) {
fprintf(stderr, "DAC not found!\n");
tlvdb_free(dacdb);
emv_pk_free(ipk);
tlvdb_free(db);
return 2;
}
if (verbose) {
printf("dac:\n");
dump_buffer(dac->value, dac->len, stdout, 0);
}
if (verbose) {
printf("dac:\n");
dump_buffer(dac->value, dac->len, stdout, 0);
}
tlvdb_free(dacdb);
emv_pk_free(ipk);
tlvdb_free(db);
tlvdb_free(dacdb);
emv_pk_free(ipk);
tlvdb_free(db);
return 0;
return 0;
}
int exec_sda_test(bool verbose)
{
int ret;
fprintf(stdout, "\n");
int ret;
fprintf(stdout, "\n");
ret = sda_test_raw(verbose);
if (ret) {
fprintf(stderr, "SDA raw test: failed\n");
return ret;
}
fprintf(stdout, "SDA raw test: passed\n");
ret = sda_test_raw(verbose);
if (ret) {
fprintf(stderr, "SDA raw test: failed\n");
return ret;
}
fprintf(stdout, "SDA raw test: passed\n");
ret = sda_test_pk(verbose);
if (ret) {
fprintf(stderr, "SDA test pk: failed\n");
return ret;
}
fprintf(stdout, "SDA test pk: passed\n");
ret = sda_test_pk(verbose);
if (ret) {
fprintf(stderr, "SDA test pk: failed\n");
return ret;
}
fprintf(stdout, "SDA test pk: passed\n");
return 0;
return 0;
}

View file

@ -26,574 +26,574 @@
#include <stddef.h>
#include <stdlib.h>
#define TLV_TAG_CLASS_MASK 0xc0
#define TLV_TAG_COMPLEX 0x20
#define TLV_TAG_VALUE_MASK 0x1f
#define TLV_TAG_VALUE_CONT 0x1f
#define TLV_TAG_INVALID 0
#define TLV_TAG_CLASS_MASK 0xc0
#define TLV_TAG_COMPLEX 0x20
#define TLV_TAG_VALUE_MASK 0x1f
#define TLV_TAG_VALUE_CONT 0x1f
#define TLV_TAG_INVALID 0
#define TLV_LEN_LONG 0x80
#define TLV_LEN_MASK 0x7f
#define TLV_LEN_INVALID (~0)
#define TLV_LEN_LONG 0x80
#define TLV_LEN_MASK 0x7f
#define TLV_LEN_INVALID (~0)
// http://radek.io/2012/11/10/magical-container_of-macro/
//#define container_of(ptr, type, member) ({
// const typeof( ((type *)0)->member ) *__mptr = (ptr);
// const typeof( ((type *)0)->member ) *__mptr = (ptr);
// (type *)( (char *)__mptr - offsetof(type,member) );})
struct tlvdb {
struct tlv tag;
struct tlvdb *next;
struct tlvdb *parent;
struct tlvdb *children;
struct tlv tag;
struct tlvdb *next;
struct tlvdb *parent;
struct tlvdb *children;
};
struct tlvdb_root {
struct tlvdb db;
size_t len;
unsigned char buf[0];
struct tlvdb db;
size_t len;
unsigned char buf[0];
};
static tlv_tag_t tlv_parse_tag(const unsigned char **buf, size_t *len)
{
tlv_tag_t tag;
tlv_tag_t tag;
if (*len == 0)
return TLV_TAG_INVALID;
tag = **buf;
--*len;
++*buf;
if ((tag & TLV_TAG_VALUE_MASK) != TLV_TAG_VALUE_CONT)
return tag;
if (*len == 0)
return TLV_TAG_INVALID;
tag = **buf;
--*len;
++*buf;
if ((tag & TLV_TAG_VALUE_MASK) != TLV_TAG_VALUE_CONT)
return tag;
if (*len == 0)
return TLV_TAG_INVALID;
if (*len == 0)
return TLV_TAG_INVALID;
tag <<= 8;
tag |= **buf;
--*len;
++*buf;
tag <<= 8;
tag |= **buf;
--*len;
++*buf;
return tag;
return tag;
}
static size_t tlv_parse_len(const unsigned char **buf, size_t *len)
{
size_t l;
size_t l;
if (*len == 0)
return TLV_LEN_INVALID;
if (*len == 0)
return TLV_LEN_INVALID;
l = **buf;
--*len;
++*buf;
l = **buf;
--*len;
++*buf;
if (!(l & TLV_LEN_LONG))
return l;
if (!(l & TLV_LEN_LONG))
return l;
size_t ll = l &~ TLV_LEN_LONG;
if (ll > 5)
return TLV_LEN_INVALID;
size_t ll = l &~ TLV_LEN_LONG;
if (ll > 5)
return TLV_LEN_INVALID;
l = 0;
for (int i = 1; i <= ll; i++) {
l = (l << 8) + **buf;
--*len;
++*buf;
}
l = 0;
for (int i = 1; i <= ll; i++) {
l = (l << 8) + **buf;
--*len;
++*buf;
}
return l;
return l;
}
bool tlv_parse_tl(const unsigned char **buf, size_t *len, struct tlv *tlv)
{
tlv->value = 0;
tlv->value = 0;
tlv->tag = tlv_parse_tag(buf, len);
if (tlv->tag == TLV_TAG_INVALID)
return false;
tlv->tag = tlv_parse_tag(buf, len);
if (tlv->tag == TLV_TAG_INVALID)
return false;
tlv->len = tlv_parse_len(buf, len);
if (tlv->len == TLV_LEN_INVALID)
return false;
tlv->len = tlv_parse_len(buf, len);
if (tlv->len == TLV_LEN_INVALID)
return false;
return true;
return true;
}
static struct tlvdb *tlvdb_parse_children(struct tlvdb *parent);
static bool tlvdb_parse_one(struct tlvdb *tlvdb,
struct tlvdb *parent,
const unsigned char **tmp,
size_t *left)
struct tlvdb *parent,
const unsigned char **tmp,
size_t *left)
{
tlvdb->next = tlvdb->children = NULL;
tlvdb->parent = parent;
tlvdb->next = tlvdb->children = NULL;
tlvdb->parent = parent;
tlvdb->tag.tag = tlv_parse_tag(tmp, left);
if (tlvdb->tag.tag == TLV_TAG_INVALID)
goto err;
tlvdb->tag.tag = tlv_parse_tag(tmp, left);
if (tlvdb->tag.tag == TLV_TAG_INVALID)
goto err;
tlvdb->tag.len = tlv_parse_len(tmp, left);
if (tlvdb->tag.len == TLV_LEN_INVALID)
goto err;
tlvdb->tag.len = tlv_parse_len(tmp, left);
if (tlvdb->tag.len == TLV_LEN_INVALID)
goto err;
if (tlvdb->tag.len > *left)
goto err;
if (tlvdb->tag.len > *left)
goto err;
tlvdb->tag.value = *tmp;
tlvdb->tag.value = *tmp;
*tmp += tlvdb->tag.len;
*left -= tlvdb->tag.len;
*tmp += tlvdb->tag.len;
*left -= tlvdb->tag.len;
if (tlv_is_constructed(&tlvdb->tag) && (tlvdb->tag.len != 0)) {
tlvdb->children = tlvdb_parse_children(tlvdb);
if (!tlvdb->children)
goto err;
} else {
tlvdb->children = NULL;
}
if (tlv_is_constructed(&tlvdb->tag) && (tlvdb->tag.len != 0)) {
tlvdb->children = tlvdb_parse_children(tlvdb);
if (!tlvdb->children)
goto err;
} else {
tlvdb->children = NULL;
}
return true;
return true;
err:
return false;
return false;
}
static struct tlvdb *tlvdb_parse_children(struct tlvdb *parent)
{
const unsigned char *tmp = parent->tag.value;
size_t left = parent->tag.len;
struct tlvdb *tlvdb, *first = NULL, *prev = NULL;
const unsigned char *tmp = parent->tag.value;
size_t left = parent->tag.len;
struct tlvdb *tlvdb, *first = NULL, *prev = NULL;
while (left != 0) {
tlvdb = malloc(sizeof(*tlvdb));
if (prev)
prev->next = tlvdb;
else
first = tlvdb;
prev = tlvdb;
while (left != 0) {
tlvdb = malloc(sizeof(*tlvdb));
if (prev)
prev->next = tlvdb;
else
first = tlvdb;
prev = tlvdb;
if (!tlvdb_parse_one(tlvdb, parent, &tmp, &left))
goto err;
if (!tlvdb_parse_one(tlvdb, parent, &tmp, &left))
goto err;
tlvdb->parent = parent;
}
tlvdb->parent = parent;
}
return first;
return first;
err:
tlvdb_free(first);
tlvdb_free(first);
return NULL;
return NULL;
}
struct tlvdb *tlvdb_parse(const unsigned char *buf, size_t len)
{
struct tlvdb_root *root;
const unsigned char *tmp;
size_t left;
struct tlvdb_root *root;
const unsigned char *tmp;
size_t left;
if (!len || !buf)
return NULL;
if (!len || !buf)
return NULL;
root = malloc(sizeof(*root) + len);
root->len = len;
memcpy(root->buf, buf, len);
root = malloc(sizeof(*root) + len);
root->len = len;
memcpy(root->buf, buf, len);
tmp = root->buf;
left = len;
tmp = root->buf;
left = len;
if (!tlvdb_parse_one(&root->db, NULL, &tmp, &left))
goto err;
if (!tlvdb_parse_one(&root->db, NULL, &tmp, &left))
goto err;
if (left)
goto err;
if (left)
goto err;
return &root->db;
return &root->db;
err:
tlvdb_free(&root->db);
tlvdb_free(&root->db);
return NULL;
return NULL;
}
struct tlvdb *tlvdb_parse_multi(const unsigned char *buf, size_t len)
{
struct tlvdb_root *root;
const unsigned char *tmp;
size_t left;
struct tlvdb_root *root;
const unsigned char *tmp;
size_t left;
if (!len || !buf)
return NULL;
if (!len || !buf)
return NULL;
root = malloc(sizeof(*root) + len);
root->len = len;
memcpy(root->buf, buf, len);
root = malloc(sizeof(*root) + len);
root->len = len;
memcpy(root->buf, buf, len);
tmp = root->buf;
left = len;
tmp = root->buf;
left = len;
if (!tlvdb_parse_one(&root->db, NULL, &tmp, &left))
goto err;
if (!tlvdb_parse_one(&root->db, NULL, &tmp, &left))
goto err;
while (left != 0) {
struct tlvdb *db = malloc(sizeof(*db));
if (!tlvdb_parse_one(db, NULL, &tmp, &left)) {
free (db);
goto err;
}
while (left != 0) {
struct tlvdb *db = malloc(sizeof(*db));
if (!tlvdb_parse_one(db, NULL, &tmp, &left)) {
free (db);
goto err;
}
tlvdb_add(&root->db, db);
}
tlvdb_add(&root->db, db);
}
return &root->db;
return &root->db;
err:
tlvdb_free(&root->db);
tlvdb_free(&root->db);
return NULL;
return NULL;
}
struct tlvdb *tlvdb_fixed(tlv_tag_t tag, size_t len, const unsigned char *value)
{
struct tlvdb_root *root = malloc(sizeof(*root) + len);
struct tlvdb_root *root = malloc(sizeof(*root) + len);
root->len = len;
memcpy(root->buf, value, len);
root->len = len;
memcpy(root->buf, value, len);
root->db.parent = root->db.next = root->db.children = NULL;
root->db.tag.tag = tag;
root->db.tag.len = len;
root->db.tag.value = root->buf;
root->db.parent = root->db.next = root->db.children = NULL;
root->db.tag.tag = tag;
root->db.tag.len = len;
root->db.tag.value = root->buf;
return &root->db;
return &root->db;
}
struct tlvdb *tlvdb_external(tlv_tag_t tag, size_t len, const unsigned char *value)
{
struct tlvdb_root *root = malloc(sizeof(*root));
struct tlvdb_root *root = malloc(sizeof(*root));
root->len = 0;
root->len = 0;
root->db.parent = root->db.next = root->db.children = NULL;
root->db.tag.tag = tag;
root->db.tag.len = len;
root->db.tag.value = value;
root->db.parent = root->db.next = root->db.children = NULL;
root->db.tag.tag = tag;
root->db.tag.len = len;
root->db.tag.value = value;
return &root->db;
return &root->db;
}
void tlvdb_free(struct tlvdb *tlvdb)
{
struct tlvdb *next = NULL;
struct tlvdb *next = NULL;
if (!tlvdb)
return;
if (!tlvdb)
return;
for (; tlvdb; tlvdb = next) {
next = tlvdb->next;
tlvdb_free(tlvdb->children);
free(tlvdb);
}
for (; tlvdb; tlvdb = next) {
next = tlvdb->next;
tlvdb_free(tlvdb->children);
free(tlvdb);
}
}
struct tlvdb *tlvdb_find_next(struct tlvdb *tlvdb, tlv_tag_t tag) {
if (!tlvdb)
return NULL;
if (!tlvdb)
return NULL;
return tlvdb_find(tlvdb->next, tag);
return tlvdb_find(tlvdb->next, tag);
}
struct tlvdb *tlvdb_find(struct tlvdb *tlvdb, tlv_tag_t tag) {
if (!tlvdb)
return NULL;
if (!tlvdb)
return NULL;
for (; tlvdb; tlvdb = tlvdb->next) {
if (tlvdb->tag.tag == tag)
return tlvdb;
}
for (; tlvdb; tlvdb = tlvdb->next) {
if (tlvdb->tag.tag == tag)
return tlvdb;
}
return NULL;
return NULL;
}
struct tlvdb *tlvdb_find_full(struct tlvdb *tlvdb, tlv_tag_t tag) {
if (!tlvdb)
return NULL;
if (!tlvdb)
return NULL;
for (; tlvdb; tlvdb = tlvdb->next) {
if (tlvdb->tag.tag == tag)
return tlvdb;
for (; tlvdb; tlvdb = tlvdb->next) {
if (tlvdb->tag.tag == tag)
return tlvdb;
if (tlvdb->children) {
struct tlvdb * ch = tlvdb_find_full(tlvdb->children, tag);
if (ch)
return ch;
}
}
if (tlvdb->children) {
struct tlvdb * ch = tlvdb_find_full(tlvdb->children, tag);
if (ch)
return ch;
}
}
return NULL;
return NULL;
}
struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]) {
int i = 0;
struct tlvdb *tnext = tlvdb;
int i = 0;
struct tlvdb *tnext = tlvdb;
while (tnext && tag[i]) {
tnext = tlvdb_find(tnext, tag[i]);
i++;
if (tag[i] && tnext) {
tnext = tnext->children;
}
}
while (tnext && tag[i]) {
tnext = tlvdb_find(tnext, tag[i]);
i++;
if (tag[i] && tnext) {
tnext = tnext->children;
}
}
return tnext;
return tnext;
}
void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other)
{
if (tlvdb == other)
return;
if (tlvdb == other)
return;
while (tlvdb->next) {
if (tlvdb->next == other)
return;
while (tlvdb->next) {
if (tlvdb->next == other)
return;
tlvdb = tlvdb->next;
}
tlvdb = tlvdb->next;
}
tlvdb->next = other;
tlvdb->next = other;
}
void tlvdb_change_or_add_node_ex(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value, struct tlvdb **tlvdb_elm)
{
struct tlvdb *telm = tlvdb_find_full(tlvdb, tag);
if (telm == NULL) {
// new tlv element
struct tlvdb *elm = tlvdb_fixed(tag, len, value);
tlvdb_add(tlvdb, elm);
if (tlvdb_elm)
*tlvdb_elm = elm;
} else {
// the same tlv structure
if (telm->tag.tag == tag && telm->tag.len == len && !memcmp(telm->tag.value, value, len))
return;
struct tlvdb *telm = tlvdb_find_full(tlvdb, tag);
if (telm == NULL) {
// new tlv element
struct tlvdb *elm = tlvdb_fixed(tag, len, value);
tlvdb_add(tlvdb, elm);
if (tlvdb_elm)
*tlvdb_elm = elm;
} else {
// the same tlv structure
if (telm->tag.tag == tag && telm->tag.len == len && !memcmp(telm->tag.value, value, len))
return;
// replace tlv element
struct tlvdb *tnewelm = tlvdb_fixed(tag, len, value);
tnewelm->next = telm->next;
tnewelm->parent = telm->parent;
// replace tlv element
struct tlvdb *tnewelm = tlvdb_fixed(tag, len, value);
tnewelm->next = telm->next;
tnewelm->parent = telm->parent;
// if telm stayed first in children chain
if (telm->parent && telm->parent->children == telm) {
telm->parent->children = tnewelm;
}
// if telm stayed first in children chain
if (telm->parent && telm->parent->children == telm) {
telm->parent->children = tnewelm;
}
// if telm have previous element
if (telm != tlvdb) {
// elm in root
struct tlvdb *celm = tlvdb;
// elm in child list of node
if (telm->parent && telm->parent->children)
celm = telm->parent->children;
// if telm have previous element
if (telm != tlvdb) {
// elm in root
struct tlvdb *celm = tlvdb;
// elm in child list of node
if (telm->parent && telm->parent->children)
celm = telm->parent->children;
// find previous element
for (; celm; celm = celm->next) {
if (celm->next == telm) {
celm->next = tnewelm;
break;
}
}
}
// find previous element
for (; celm; celm = celm->next) {
if (celm->next == telm) {
celm->next = tnewelm;
break;
}
}
}
// free old element with childrens
telm->next = NULL;
tlvdb_free(telm);
// free old element with childrens
telm->next = NULL;
tlvdb_free(telm);
if (tlvdb_elm)
*tlvdb_elm = tnewelm;
}
if (tlvdb_elm)
*tlvdb_elm = tnewelm;
}
return;
return;
}
void tlvdb_change_or_add_node(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value)
{
tlvdb_change_or_add_node_ex(tlvdb, tag, len, value, NULL);
tlvdb_change_or_add_node_ex(tlvdb, tag, len, value, NULL);
}
void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level)
{
struct tlvdb *next = NULL;
struct tlvdb *next = NULL;
if (!tlvdb)
return;
if (!tlvdb)
return;
for (; tlvdb; tlvdb = next) {
next = tlvdb->next;
cb(data, &tlvdb->tag, level, (tlvdb->children == NULL));
tlvdb_visit(tlvdb->children, cb, data, level + 1);
}
for (; tlvdb; tlvdb = next) {
next = tlvdb->next;
cb(data, &tlvdb->tag, level, (tlvdb->children == NULL));
tlvdb_visit(tlvdb->children, cb, data, level + 1);
}
}
static const struct tlvdb *tlvdb_next(const struct tlvdb *tlvdb)
{
if (tlvdb->children)
return tlvdb->children;
if (tlvdb->children)
return tlvdb->children;
while (tlvdb) {
if (tlvdb->next)
return tlvdb->next;
while (tlvdb) {
if (tlvdb->next)
return tlvdb->next;
tlvdb = tlvdb->parent;
}
tlvdb = tlvdb->parent;
}
return NULL;
return NULL;
}
const struct tlv *tlvdb_get(const struct tlvdb *tlvdb, tlv_tag_t tag, const struct tlv *prev)
{
if (prev) {
// tlvdb = tlvdb_next(container_of(prev, struct tlvdb, tag));
tlvdb = tlvdb_next((struct tlvdb *)prev);
}
if (prev) {
// tlvdb = tlvdb_next(container_of(prev, struct tlvdb, tag));
tlvdb = tlvdb_next((struct tlvdb *)prev);
}
while (tlvdb) {
if (tlvdb->tag.tag == tag)
return &tlvdb->tag;
while (tlvdb) {
if (tlvdb->tag.tag == tag)
return &tlvdb->tag;
tlvdb = tlvdb_next(tlvdb);
}
tlvdb = tlvdb_next(tlvdb);
}
return NULL;
return NULL;
}
const struct tlv *tlvdb_get_inchild(const struct tlvdb *tlvdb, tlv_tag_t tag, const struct tlv *prev) {
tlvdb = tlvdb->children;
return tlvdb_get(tlvdb, tag, prev);
tlvdb = tlvdb->children;
return tlvdb_get(tlvdb, tag, prev);
}
const struct tlv *tlvdb_get_tlv(const struct tlvdb *tlvdb) {
if (tlvdb)
return &tlvdb->tag;
else
return NULL;
if (tlvdb)
return &tlvdb->tag;
else
return NULL;
}
unsigned char *tlv_encode(const struct tlv *tlv, size_t *len)
{
size_t size = tlv->len;
unsigned char *data;
size_t pos;
size_t size = tlv->len;
unsigned char *data;
size_t pos;
if (tlv->tag > 0x100)
size += 2;
else
size += 1;
if (tlv->tag > 0x100)
size += 2;
else
size += 1;
if (tlv->len > 0x7f)
size += 2;
else
size += 1;
if (tlv->len > 0x7f)
size += 2;
else
size += 1;
data = malloc(size);
if (!data) {
*len = 0;
return NULL;
}
data = malloc(size);
if (!data) {
*len = 0;
return NULL;
}
pos = 0;
pos = 0;
if (tlv->tag > 0x100) {
data[pos++] = tlv->tag >> 8;
data[pos++] = tlv->tag & 0xff;
} else
data[pos++] = tlv->tag;
if (tlv->tag > 0x100) {
data[pos++] = tlv->tag >> 8;
data[pos++] = tlv->tag & 0xff;
} else
data[pos++] = tlv->tag;
if (tlv->len > 0x7f) {
data[pos++] = 0x81;
data[pos++] = tlv->len;
} else
data[pos++] = tlv->len;
if (tlv->len > 0x7f) {
data[pos++] = 0x81;
data[pos++] = tlv->len;
} else
data[pos++] = tlv->len;
memcpy(data + pos, tlv->value, tlv->len);
pos += tlv->len;
memcpy(data + pos, tlv->value, tlv->len);
pos += tlv->len;
*len = pos;
return data;
*len = pos;
return data;
}
bool tlv_is_constructed(const struct tlv *tlv)
{
return (tlv->tag < 0x100 ? tlv->tag : tlv->tag >> 8) & TLV_TAG_COMPLEX;
return (tlv->tag < 0x100 ? tlv->tag : tlv->tag >> 8) & TLV_TAG_COMPLEX;
}
bool tlv_equal(const struct tlv *a, const struct tlv *b)
{
if (!a && !b)
return true;
if (!a && !b)
return true;
if (!a || !b)
return false;
if (!a || !b)
return false;
return a->tag == b->tag && a->len == b->len && !memcmp(a->value, b->value, a->len);
return a->tag == b->tag && a->len == b->len && !memcmp(a->value, b->value, a->len);
}
struct tlvdb *tlvdb_elm_get_next(struct tlvdb *tlvdb)
{
return tlvdb->next;
return tlvdb->next;
}
struct tlvdb *tlvdb_elm_get_children(struct tlvdb *tlvdb)
{
return tlvdb->children;
return tlvdb->children;
}
struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb)
{
return tlvdb->parent;
return tlvdb->parent;
}
bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value)
{
const struct tlv *tlvelm = tlvdb_get(tlvRoot, tag, NULL);
return tlv_get_uint8(tlvelm, value);
const struct tlv *tlvelm = tlvdb_get(tlvRoot, tag, NULL);
return tlv_get_uint8(tlvelm, value);
}
bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value)
{
*value = 0;
if (etlv)
{
if (etlv->len == 0)
return true;
*value = 0;
if (etlv)
{
if (etlv->len == 0)
return true;
if (etlv->len == 1)
{
*value = etlv->value[0];
return true;
}
}
return false;
if (etlv->len == 1)
{
*value = etlv->value[0];
return true;
}
}
return false;
}
bool tlv_get_int(const struct tlv *etlv, int *value)
{
*value = 0;
if (etlv)
{
if (etlv->len == 0)
return true;
*value = 0;
if (etlv)
{
if (etlv->len == 0)
return true;
if (etlv->len <= 4)
{
for (int i = 0; i < etlv->len; i++)
{
*value += etlv->value[i] * (1 << (i * 8));
}
return true;
}
}
return false;
if (etlv->len <= 4)
{
for (int i = 0; i < etlv->len; i++)
{
*value += etlv->value[i] * (1 << (i * 8));
}
return true;
}
}
return false;
}

View file

@ -25,9 +25,9 @@
typedef uint32_t tlv_tag_t;
struct tlv {
tlv_tag_t tag;
size_t len;
const unsigned char *value;
tlv_tag_t tag;
size_t len;
const unsigned char *value;
};
struct tlvdb;