| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /* base64_dec.c */
- /*
- * This file is part of the ARM-Crypto-Lib.
- * Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /**
- * base64 decoder (RFC3548)
- * Author: Daniel Otte
- * License: GPLv3
- *
- *
- */
- #include <stdint.h>
- #include <crypto/base64_dec.h>
- /*
- #define USE_GCC_EXTENSION
- */
- #ifdef USE_GCC_EXTENSION
- static
- int ascii2bit6(char a){
- switch(a){
- case 'A'...'Z':
- return a-'A';
- case 'a'...'z':
- return a-'a'+26;
- case '0'...'9':
- return a-'0'+52;
- case '+':
- case '-':
- return 62;
- case '/':
- case '_':
- return 63;
- default:
- return -1;
- }
- }
- #else
- static
- uint8_t ascii2bit6(char a){
- int r;
- switch(a>>4){
- case 0x5:
- case 0x4:
- r=a-'A';
- if(r<0 || r>25){
- return -1;
- } else {
- return r;
- }
- case 0x7:
- case 0x6:
- r=a-'a';
- if(r<0 || r>25){
- return -1;
- } else {
- return r+26;
- }
- break;
- case 0x3:
- if(a>'9')
- return -1;
- return a-'0'+52;
- default:
- break;
- }
- switch (a){
- case '+':
- case '-':
- return 62;
- case '/':
- case '_':
- return 63;
- default:
- return 0xff;
- }
- }
- #endif
- int base64_binlength(char* str, uint8_t strict){
- int l=0;
- uint8_t term=0;
- for(;;){
- if(*str=='\0')
- break;
- if(*str=='\n' || *str=='\r'){
- str++;
- continue;
- }
- if(*str=='='){
- term++;
- str++;
- if(term==2){
- break;
- }
- continue;
- }
- if(term)
- return -1;
- if(ascii2bit6(*str)==-1){
- if(strict)
- return -1;
- } else {
- l++;
- }
- str++;
- }
- switch(term){
- case 0:
- if(l%4!=0)
- return -1;
- return l/4*3;
- case 1:
- if(l%4!=3)
- return -1;
- return (l+1)/4*3-1;
- case 2:
- if(l%4!=2)
- return -1;
- return (l+2)/4*3-2;
- default:
- return -1;
- }
- }
- /*
- |543210543210543210543210|
- |765432107654321076543210|
- . . . .
- |54321054|32105432|10543210|
- |76543210|76543210|76543210|
- */
- int base64dec(void* dest, const char* b64str, uint8_t strict){
- uint8_t buffer[4];
- uint8_t idx=0;
- uint8_t term=0;
- for(;;){
- buffer[idx]= ascii2bit6(*b64str);
-
- if(buffer[idx]==0xFF){
- if(*b64str=='='){
- term++;
- b64str++;
- if(term==2)
- goto finalize; /* definitly the end */
- }else{
- if(*b64str == '\0'){
- goto finalize; /* definitly the end */
- }else{
- if(*b64str == '\r' || *b64str == '\n' || !(strict)){
- b64str++; /* charcters that we simply ignore */
- }else{
- return -1;
- }
- }
- }
- }else{
- if(term)
- return -1; /* this happens if we get a '=' in the stream */
- idx++;
- b64str++;
- }
- if(idx==4){
- ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
- ((uint8_t*)dest)[1] = buffer[1]<<4 | buffer[2]>>2;
- ((uint8_t*)dest)[2] = buffer[2]<<6 | buffer[3];
- dest = (uint8_t*)dest +3;
- idx=0;
- }
- }
- finalize:
- /* the final touch */
- if(idx==0)
- return 0;
- if(term==1){
- ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
- ((uint8_t*)dest)[1] = buffer[1]<<4 | buffer[2]>>2;
- return 0;
- }
- if(term==2){
- ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
- return 0;
- }
- return -1;
- }
|