key.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* Key to pathname encoder
  3. *
  4. * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #include <linux/slab.h>
  8. #include "internal.h"
  9. static const char cachefiles_charmap[64] =
  10. "0123456789" /* 0 - 9 */
  11. "abcdefghijklmnopqrstuvwxyz" /* 10 - 35 */
  12. "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 36 - 61 */
  13. "_-" /* 62 - 63 */
  14. ;
  15. static const char cachefiles_filecharmap[256] = {
  16. /* we skip space and tab and control chars */
  17. [33 ... 46] = 1, /* '!' -> '.' */
  18. /* we skip '/' as it's significant to pathwalk */
  19. [48 ... 127] = 1, /* '0' -> '~' */
  20. };
  21. /*
  22. * turn the raw key into something cooked
  23. * - the raw key should include the length in the two bytes at the front
  24. * - the key may be up to 514 bytes in length (including the length word)
  25. * - "base64" encode the strange keys, mapping 3 bytes of raw to four of
  26. * cooked
  27. * - need to cut the cooked key into 252 char lengths (189 raw bytes)
  28. */
  29. char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type)
  30. {
  31. unsigned char csum, ch;
  32. unsigned int acc;
  33. char *key;
  34. int loop, len, max, seg, mark, print;
  35. _enter(",%d", keylen);
  36. BUG_ON(keylen < 2 || keylen > 514);
  37. csum = raw[0] + raw[1];
  38. print = 1;
  39. for (loop = 2; loop < keylen; loop++) {
  40. ch = raw[loop];
  41. csum += ch;
  42. print &= cachefiles_filecharmap[ch];
  43. }
  44. if (print) {
  45. /* if the path is usable ASCII, then we render it directly */
  46. max = keylen - 2;
  47. max += 2; /* two base64'd length chars on the front */
  48. max += 5; /* @checksum/M */
  49. max += 3 * 2; /* maximum number of segment dividers (".../M")
  50. * is ((514 + 251) / 252) = 3
  51. */
  52. max += 1; /* NUL on end */
  53. } else {
  54. /* calculate the maximum length of the cooked key */
  55. keylen = (keylen + 2) / 3;
  56. max = keylen * 4;
  57. max += 5; /* @checksum/M */
  58. max += 3 * 2; /* maximum number of segment dividers (".../M")
  59. * is ((514 + 188) / 189) = 3
  60. */
  61. max += 1; /* NUL on end */
  62. }
  63. max += 1; /* 2nd NUL on end */
  64. _debug("max: %d", max);
  65. key = kmalloc(max, cachefiles_gfp);
  66. if (!key)
  67. return NULL;
  68. len = 0;
  69. /* build the cooked key */
  70. sprintf(key, "@%02x%c+", (unsigned) csum, 0);
  71. len = 5;
  72. mark = len - 1;
  73. if (print) {
  74. acc = *(uint16_t *) raw;
  75. raw += 2;
  76. key[len + 1] = cachefiles_charmap[acc & 63];
  77. acc >>= 6;
  78. key[len] = cachefiles_charmap[acc & 63];
  79. len += 2;
  80. seg = 250;
  81. for (loop = keylen; loop > 0; loop--) {
  82. if (seg <= 0) {
  83. key[len++] = '\0';
  84. mark = len;
  85. key[len++] = '+';
  86. seg = 252;
  87. }
  88. key[len++] = *raw++;
  89. ASSERT(len < max);
  90. }
  91. switch (type) {
  92. case FSCACHE_COOKIE_TYPE_INDEX: type = 'I'; break;
  93. case FSCACHE_COOKIE_TYPE_DATAFILE: type = 'D'; break;
  94. default: type = 'S'; break;
  95. }
  96. } else {
  97. seg = 252;
  98. for (loop = keylen; loop > 0; loop--) {
  99. if (seg <= 0) {
  100. key[len++] = '\0';
  101. mark = len;
  102. key[len++] = '+';
  103. seg = 252;
  104. }
  105. acc = *raw++;
  106. acc |= *raw++ << 8;
  107. acc |= *raw++ << 16;
  108. _debug("acc: %06x", acc);
  109. key[len++] = cachefiles_charmap[acc & 63];
  110. acc >>= 6;
  111. key[len++] = cachefiles_charmap[acc & 63];
  112. acc >>= 6;
  113. key[len++] = cachefiles_charmap[acc & 63];
  114. acc >>= 6;
  115. key[len++] = cachefiles_charmap[acc & 63];
  116. ASSERT(len < max);
  117. }
  118. switch (type) {
  119. case FSCACHE_COOKIE_TYPE_INDEX: type = 'J'; break;
  120. case FSCACHE_COOKIE_TYPE_DATAFILE: type = 'E'; break;
  121. default: type = 'T'; break;
  122. }
  123. }
  124. key[mark] = type;
  125. key[len++] = 0;
  126. key[len] = 0;
  127. _leave(" = %p %d", key, len);
  128. return key;
  129. }