Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*********************************************************************
  2. * Filename:   base64.c
  3. * Author:     Brad Conte (brad AT bradconte.com)
  4. * Copyright:
  5. * Disclaimer: This code is presented "as is" without any guarantees.
  6. * Details:    Implementation of the Base64 encoding algorithm.
  7. *********************************************************************/
  8.  
  9. /*************************** HEADER FILES ***************************/
  10. #include <stdlib.h>
  11. #include <cryptal/base64.h>
  12.  
  13. /****************************** MACROS ******************************/
  14. #define NEWLINE_INVL 76
  15.  
  16. /**************************** VARIABLES *****************************/
  17. // Note: To change the charset to a URL encoding, replace the '+' and '/' with '*' and '-'
  18. static const BYTE charset[]={"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
  19.  
  20. /*********************** FUNCTION DEFINITIONS ***********************/
  21. BYTE revchar(char ch)
  22. {
  23.         if (ch >= 'A' && ch <= 'Z')
  24.                 ch -= 'A';
  25.         else if (ch >= 'a' && ch <='z')
  26.                 ch = ch - 'a' + 26;
  27.         else if (ch >= '0' && ch <='9')
  28.                 ch = ch - '0' + 52;
  29.         else if (ch == '+')
  30.                 ch = 62;
  31.         else if (ch == '/')
  32.                 ch = 63;
  33.  
  34.         return(ch);
  35. }
  36.  
  37. size_t base64_encode(const BYTE in[], BYTE out[], size_t len, int newline_flag)
  38. {
  39.         size_t idx, idx2, blks, blk_ceiling, left_over, newline_count = 0;
  40.  
  41.         blks = (len / 3);
  42.         left_over = len % 3;
  43.  
  44.         if (out == NULL) {
  45.                 idx2 = blks * 4 ;
  46.                 if (left_over)
  47.                         idx2 += 4;
  48.                 if (newline_flag)
  49.                         idx2 += len / 57;   // (NEWLINE_INVL / 4) * 3 = 57. One newline per 57 input bytes.
  50.         }
  51.         else {
  52.                 // Since 3 input bytes = 4 output bytes, determine out how many even sets of
  53.                 // 3 bytes the input has.
  54.                 blk_ceiling = blks * 3;
  55.                 for (idx = 0, idx2 = 0; idx < blk_ceiling; idx += 3, idx2 += 4) {
  56.                         out[idx2]     = charset[in[idx] >> 2];
  57.                         out[idx2 + 1] = charset[((in[idx] & 0x03) << 4) | (in[idx + 1] >> 4)];
  58.                         out[idx2 + 2] = charset[((in[idx + 1] & 0x0f) << 2) | (in[idx + 2] >> 6)];
  59.                         out[idx2 + 3] = charset[in[idx + 2] & 0x3F];
  60.                         // The offical standard requires a newline every 76 characters.
  61.                         // (Eg, first newline is character 77 of the output.)
  62.                         if (((idx2 - newline_count + 4) % NEWLINE_INVL == 0) && newline_flag) {
  63.                                 out[idx2 + 4] = '\n';
  64.                                 idx2++;
  65.                                 newline_count++;
  66.                         }
  67.                 }
  68.  
  69.                 if (left_over == 1) {
  70.                         out[idx2]     = charset[in[idx] >> 2];
  71.                         out[idx2 + 1] = charset[(in[idx] & 0x03) << 4];
  72.                         out[idx2 + 2] = '=';
  73.                         out[idx2 + 3] = '=';
  74.                         idx2 += 4;
  75.                 }
  76.                 else if (left_over == 2) {
  77.                         out[idx2]     = charset[in[idx] >> 2];
  78.                         out[idx2 + 1] = charset[((in[idx] & 0x03) << 4) | (in[idx + 1] >> 4)];
  79.                         out[idx2 + 2] = charset[(in[idx + 1] & 0x0F) << 2];
  80.                         out[idx2 + 3] = '=';
  81.                         idx2 += 4;
  82.                 }
  83.         }
  84.  
  85.         return(idx2);
  86. }
  87.  
  88. size_t base64_decode(const BYTE in[], BYTE out[], size_t len)
  89. {
  90.         BYTE ch;
  91.         size_t idx, idx2, blks, blk_ceiling, left_over;
  92.  
  93.         if (in[len - 1] == '=')
  94.                 len--;
  95.         if (in[len - 1] == '=')
  96.                 len--;
  97.  
  98.         blks = len / 4;
  99.         left_over = len % 4;
  100.  
  101.         if (out == NULL) {
  102.                 if (len >= 77 && in[NEWLINE_INVL] == '\n')   // Verify that newlines where used.
  103.                         len -= len / (NEWLINE_INVL + 1);
  104.                 blks = len / 4;
  105.                 left_over = len % 4;
  106.  
  107.                 idx = blks * 3;
  108.                 if (left_over == 2)
  109.                         idx ++;
  110.                 else if (left_over == 3)
  111.                         idx += 2;
  112.         }
  113.         else {
  114.                 blk_ceiling = blks * 4;
  115.                 for (idx = 0, idx2 = 0; idx2 < blk_ceiling; idx += 3, idx2 += 4) {
  116.                         if (in[idx2] == '\n')
  117.                                 idx2++;
  118.                         out[idx]     = (revchar(in[idx2]) << 2) | ((revchar(in[idx2 + 1]) & 0x30) >> 4);
  119.                         out[idx + 1] = (revchar(in[idx2 + 1]) << 4) | (revchar(in[idx2 + 2]) >> 2);
  120.                         out[idx + 2] = (revchar(in[idx2 + 2]) << 6) | revchar(in[idx2 + 3]);
  121.                 }
  122.  
  123.                 if (left_over == 2) {
  124.                         out[idx]     = (revchar(in[idx2]) << 2) | ((revchar(in[idx2 + 1]) & 0x30) >> 4);
  125.                         idx++;
  126.                 }
  127.                 else if (left_over == 3) {
  128.                         out[idx]     = (revchar(in[idx2]) << 2) | ((revchar(in[idx2 + 1]) & 0x30) >> 4);
  129.                         out[idx + 1] = (revchar(in[idx2 + 1]) << 4) | (revchar(in[idx2 + 2]) >> 2);
  130.                         idx += 2;
  131.                 }
  132.         }
  133.  
  134.         return(idx);
  135. }
  136.