base64_dec.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /* base64_dec.c */
  2. /*
  3. * This file is part of the ARM-Crypto-Lib.
  4. * Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /**
  20. * base64 decoder (RFC3548)
  21. * Author: Daniel Otte
  22. * License: GPLv3
  23. *
  24. *
  25. */
  26. #include <stdint.h>
  27. #include <crypto/base64_dec.h>
  28. /*
  29. #define USE_GCC_EXTENSION
  30. */
  31. #ifdef USE_GCC_EXTENSION
  32. static
  33. int ascii2bit6(char a){
  34. switch(a){
  35. case 'A'...'Z':
  36. return a-'A';
  37. case 'a'...'z':
  38. return a-'a'+26;
  39. case '0'...'9':
  40. return a-'0'+52;
  41. case '+':
  42. case '-':
  43. return 62;
  44. case '/':
  45. case '_':
  46. return 63;
  47. default:
  48. return -1;
  49. }
  50. }
  51. #else
  52. static
  53. uint8_t ascii2bit6(char a){
  54. int r;
  55. switch(a>>4){
  56. case 0x5:
  57. case 0x4:
  58. r=a-'A';
  59. if(r<0 || r>25){
  60. return -1;
  61. } else {
  62. return r;
  63. }
  64. case 0x7:
  65. case 0x6:
  66. r=a-'a';
  67. if(r<0 || r>25){
  68. return -1;
  69. } else {
  70. return r+26;
  71. }
  72. break;
  73. case 0x3:
  74. if(a>'9')
  75. return -1;
  76. return a-'0'+52;
  77. default:
  78. break;
  79. }
  80. switch (a){
  81. case '+':
  82. case '-':
  83. return 62;
  84. case '/':
  85. case '_':
  86. return 63;
  87. default:
  88. return 0xff;
  89. }
  90. }
  91. #endif
  92. int base64_binlength(char* str, uint8_t strict){
  93. int l=0;
  94. uint8_t term=0;
  95. for(;;){
  96. if(*str=='\0')
  97. break;
  98. if(*str=='\n' || *str=='\r'){
  99. str++;
  100. continue;
  101. }
  102. if(*str=='='){
  103. term++;
  104. str++;
  105. if(term==2){
  106. break;
  107. }
  108. continue;
  109. }
  110. if(term)
  111. return -1;
  112. if(ascii2bit6(*str)==-1){
  113. if(strict)
  114. return -1;
  115. } else {
  116. l++;
  117. }
  118. str++;
  119. }
  120. switch(term){
  121. case 0:
  122. if(l%4!=0)
  123. return -1;
  124. return l/4*3;
  125. case 1:
  126. if(l%4!=3)
  127. return -1;
  128. return (l+1)/4*3-1;
  129. case 2:
  130. if(l%4!=2)
  131. return -1;
  132. return (l+2)/4*3-2;
  133. default:
  134. return -1;
  135. }
  136. }
  137. /*
  138. |543210543210543210543210|
  139. |765432107654321076543210|
  140. . . . .
  141. |54321054|32105432|10543210|
  142. |76543210|76543210|76543210|
  143. */
  144. int base64dec(void* dest, const char* b64str, uint8_t strict){
  145. uint8_t buffer[4];
  146. uint8_t idx=0;
  147. uint8_t term=0;
  148. for(;;){
  149. buffer[idx]= ascii2bit6(*b64str);
  150. if(buffer[idx]==0xFF){
  151. if(*b64str=='='){
  152. term++;
  153. b64str++;
  154. if(term==2)
  155. goto finalize; /* definitly the end */
  156. }else{
  157. if(*b64str == '\0'){
  158. goto finalize; /* definitly the end */
  159. }else{
  160. if(*b64str == '\r' || *b64str == '\n' || !(strict)){
  161. b64str++; /* charcters that we simply ignore */
  162. }else{
  163. return -1;
  164. }
  165. }
  166. }
  167. }else{
  168. if(term)
  169. return -1; /* this happens if we get a '=' in the stream */
  170. idx++;
  171. b64str++;
  172. }
  173. if(idx==4){
  174. ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
  175. ((uint8_t*)dest)[1] = buffer[1]<<4 | buffer[2]>>2;
  176. ((uint8_t*)dest)[2] = buffer[2]<<6 | buffer[3];
  177. dest = (uint8_t*)dest +3;
  178. idx=0;
  179. }
  180. }
  181. finalize:
  182. /* the final touch */
  183. if(idx==0)
  184. return 0;
  185. if(term==1){
  186. ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
  187. ((uint8_t*)dest)[1] = buffer[1]<<4 | buffer[2]>>2;
  188. return 0;
  189. }
  190. if(term==2){
  191. ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
  192. return 0;
  193. }
  194. return -1;
  195. }