base64.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * base64.c - RFC4648-compliant base64 encoding
  4. *
  5. * Copyright (c) 2020 Hannes Reinecke, SUSE
  6. *
  7. * Based on the base64url routines from fs/crypto/fname.c
  8. * (which are using the URL-safe base64 encoding),
  9. * modified to use the standard coding table from RFC4648 section 4.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/types.h>
  13. #include <linux/export.h>
  14. #include <linux/string.h>
  15. #include <linux/base64.h>
  16. static const char base64_table[65] =
  17. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  18. /**
  19. * base64_encode() - base64-encode some binary data
  20. * @src: the binary data to encode
  21. * @srclen: the length of @src in bytes
  22. * @dst: (output) the base64-encoded string. Not NUL-terminated.
  23. *
  24. * Encodes data using base64 encoding, i.e. the "Base 64 Encoding" specified
  25. * by RFC 4648, including the '='-padding.
  26. *
  27. * Return: the length of the resulting base64-encoded string in bytes.
  28. */
  29. int base64_encode(const u8 *src, int srclen, char *dst)
  30. {
  31. u32 ac = 0;
  32. int bits = 0;
  33. int i;
  34. char *cp = dst;
  35. for (i = 0; i < srclen; i++) {
  36. ac = (ac << 8) | src[i];
  37. bits += 8;
  38. do {
  39. bits -= 6;
  40. *cp++ = base64_table[(ac >> bits) & 0x3f];
  41. } while (bits >= 6);
  42. }
  43. if (bits) {
  44. *cp++ = base64_table[(ac << (6 - bits)) & 0x3f];
  45. bits -= 6;
  46. }
  47. while (bits < 0) {
  48. *cp++ = '=';
  49. bits += 2;
  50. }
  51. return cp - dst;
  52. }
  53. EXPORT_SYMBOL_GPL(base64_encode);
  54. /**
  55. * base64_decode() - base64-decode a string
  56. * @src: the string to decode. Doesn't need to be NUL-terminated.
  57. * @srclen: the length of @src in bytes
  58. * @dst: (output) the decoded binary data
  59. *
  60. * Decodes a string using base64 encoding, i.e. the "Base 64 Encoding"
  61. * specified by RFC 4648, including the '='-padding.
  62. *
  63. * This implementation hasn't been optimized for performance.
  64. *
  65. * Return: the length of the resulting decoded binary data in bytes,
  66. * or -1 if the string isn't a valid base64 string.
  67. */
  68. int base64_decode(const char *src, int srclen, u8 *dst)
  69. {
  70. u32 ac = 0;
  71. int bits = 0;
  72. int i;
  73. u8 *bp = dst;
  74. for (i = 0; i < srclen; i++) {
  75. const char *p = strchr(base64_table, src[i]);
  76. if (src[i] == '=') {
  77. ac = (ac << 6);
  78. bits += 6;
  79. if (bits >= 8)
  80. bits -= 8;
  81. continue;
  82. }
  83. if (p == NULL || src[i] == 0)
  84. return -1;
  85. ac = (ac << 6) | (p - base64_table);
  86. bits += 6;
  87. if (bits >= 8) {
  88. bits -= 8;
  89. *bp++ = (u8)(ac >> bits);
  90. }
  91. }
  92. if (ac & ((1 << bits) - 1))
  93. return -1;
  94. return bp - dst;
  95. }
  96. EXPORT_SYMBOL_GPL(base64_decode);