passy_common.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "passy_common.h"
  2. #define PASSY_WORKER_MAX_BUFFER_SIZE 128
  3. #define TAG "PassyCommon"
  4. static char asn1_log[PASSY_WORKER_MAX_BUFFER_SIZE];
  5. int print_struct_callback(const void* buffer, size_t size, void* app_key) {
  6. if(app_key) {
  7. char* str = (char*)app_key;
  8. size_t next = strlen(str);
  9. strncpy(str + next, buffer, size);
  10. } else {
  11. uint8_t next = strlen(asn1_log);
  12. strncpy(asn1_log + next, buffer, size);
  13. }
  14. return 0;
  15. }
  16. void passy_log_bitbuffer(char* tag, char* prefix, BitBuffer* buffer) {
  17. furi_assert(buffer);
  18. size_t length = bit_buffer_get_size_bytes(buffer);
  19. const uint8_t* data = bit_buffer_get_data(buffer);
  20. char display[PASSY_WORKER_MAX_BUFFER_SIZE * 2 + 1];
  21. size_t limit = MIN((size_t)PASSY_WORKER_MAX_BUFFER_SIZE, length);
  22. memset(display, 0, sizeof(display));
  23. for(uint8_t i = 0; i < limit; i++) {
  24. snprintf(display + (i * 2), sizeof(display), "%02x", data[i]);
  25. }
  26. if(prefix) {
  27. FURI_LOG_D(tag, "%s %d: %s", prefix, length, display);
  28. } else {
  29. FURI_LOG_D(tag, "Buffer %d: %s", length, display);
  30. }
  31. }
  32. void passy_log_buffer(char* tag, char* prefix, uint8_t* buffer, size_t buffer_len) {
  33. char display[PASSY_WORKER_MAX_BUFFER_SIZE * 2 + 1];
  34. size_t limit = MIN((size_t)PASSY_WORKER_MAX_BUFFER_SIZE, buffer_len);
  35. memset(display, 0, sizeof(display));
  36. for(uint8_t i = 0; i < limit; i++) {
  37. snprintf(display + (i * 2), sizeof(display), "%02x", buffer[i]);
  38. }
  39. if(prefix) {
  40. FURI_LOG_D(tag, "%s %d: %s", prefix, limit, display);
  41. } else {
  42. FURI_LOG_D(tag, "Buffer %d: %s", limit, display);
  43. }
  44. }
  45. // ISO/IEC 9797-1 MAC Algorithm 3
  46. void passy_mac(uint8_t* key, uint8_t* data, size_t data_length, uint8_t* mac, bool prepadded) {
  47. size_t block_count = data_length / 8;
  48. uint8_t y[8];
  49. memset(y, 0, sizeof(y));
  50. for(size_t i = 0; i < block_count; i++) {
  51. uint8_t* x = data + (i * 8);
  52. //passy_log_buffer(TAG, "x", x, 8);
  53. uint8_t iv[8];
  54. memcpy(iv, y, sizeof(y));
  55. mbedtls_des_context ctx;
  56. mbedtls_des_init(&ctx);
  57. mbedtls_des_setkey_enc(&ctx, key); // uses 8 bytes
  58. mbedtls_des_crypt_cbc(&ctx, MBEDTLS_DES_ENCRYPT, 8, iv, x, y);
  59. mbedtls_des_free(&ctx);
  60. //passy_log_buffer(TAG, "y", y, 8);
  61. }
  62. mbedtls_des_context ctx;
  63. if(!prepadded) {
  64. // last block
  65. uint8_t last_block[8] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  66. uint8_t iv[8];
  67. memcpy(iv, y, sizeof(y));
  68. mbedtls_des_init(&ctx);
  69. mbedtls_des_setkey_enc(&ctx, key); // uses 8 bytes
  70. mbedtls_des_crypt_cbc(&ctx, MBEDTLS_DES_ENCRYPT, 8, iv, last_block, y);
  71. //passy_log_buffer(TAG, "y", y, 8);
  72. }
  73. uint8_t b[8];
  74. mbedtls_des_init(&ctx);
  75. mbedtls_des_setkey_dec(&ctx, key + 8); // uses 8 bytes
  76. mbedtls_des_crypt_ecb(&ctx, y, b);
  77. //passy_log_buffer(TAG, "b", b, 8);
  78. mbedtls_des_init(&ctx);
  79. mbedtls_des_setkey_enc(&ctx, key); // uses 8 bytes
  80. mbedtls_des_crypt_ecb(&ctx, b, mac);
  81. //passy_log_buffer(TAG, "mac", mac, 8);
  82. mbedtls_des_free(&ctx);
  83. }
  84. // https://en.wikipedia.org/wiki/Machine-readable_passport
  85. char passy_checksum(char* str) {
  86. uint8_t values[] = {
  87. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
  88. 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
  89. // < = filler
  90. // A = 10
  91. // B = 11
  92. // C = 12
  93. // D = 13
  94. // E = 14
  95. // F = 15
  96. // G = 16
  97. // H = 17
  98. // I = 18
  99. // J = 19
  100. // K = 20
  101. // L = 21
  102. // M = 22
  103. // N = 23
  104. // O = 24
  105. // P = 25
  106. // Q = 26
  107. // R = 27
  108. // S = 28
  109. // T = 29
  110. // U = 30
  111. // V = 31
  112. // W = 32
  113. // X = 33
  114. // Y = 34
  115. // Z = 35
  116. };
  117. size_t sum = 0;
  118. uint8_t weight_map[] = {7, 3, 1};
  119. for(uint8_t i = 0; i < strlen(str); i++) {
  120. uint8_t value;
  121. uint8_t weight = weight_map[(i % 3)];
  122. if(str[i] >= '0' && str[i] <= '9') {
  123. value = values[str[i] - '0'];
  124. } else if(str[i] >= 'A' && str[i] <= 'Z') {
  125. value = values[str[i] - 'A' + 10];
  126. } else if(str[i] >= 'a' && str[i] <= 'z') {
  127. value = values[str[i] - 'a' + 10];
  128. } else if(str[i] == '<') {
  129. value = 0;
  130. } else {
  131. FURI_LOG_E(TAG, "Invalid character %02x", str[i]);
  132. return -1;
  133. }
  134. sum += value * weight;
  135. }
  136. return 0x30 + (sum % 10);
  137. }