]> git.cryptolib.org Git - avr-crypto-lib.git/blobdiff - hmac-md5/base64_dec.c
modified structure
[avr-crypto-lib.git] / hmac-md5 / base64_dec.c
diff --git a/hmac-md5/base64_dec.c b/hmac-md5/base64_dec.c
new file mode 100644 (file)
index 0000000..f057f54
--- /dev/null
@@ -0,0 +1,246 @@
+/* base64_dec.c */
+/*
+ *   This file is part of the AVR-Crypto-Lib.
+ *   Copyright (C) 2006, 2007, 2008  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 "base64_dec.h"
+
+#include "test_src/cli.h"
+
+/*
+ #define USE_GCC_EXTENSION
+*/
+#if 1
+
+#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
+
+#else
+
+static 
+uint8_t ascii2bit6(uint8_t a){
+       if(a>='A' && a<='Z'){
+               return a-'A';
+       } else {
+               if(a>='a' && a<= 'z'){
+                       return a-'a'+26;
+               } else {
+                       if(a>='0' && a<='9'){
+                               return a-'0'+52;
+                       } else {
+                               if(a=='+' || a=='-'){
+                                       return 62;
+                               } else {
+                                       if(a=='/' || a=='_'){
+                                               return 63;
+                                       } else {
+                                               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, char* b64str, uint8_t strict){
+       uint8_t buffer[4];
+       uint8_t idx=0;
+       uint8_t term=0;
+       for(;;){
+//             cli_putstr_P(PSTR("\r\n  DBG: got 0x"));
+//             cli_hexdump(b64str, 1);
+               buffer[idx]= ascii2bit6(*b64str);
+//             cli_putstr_P(PSTR(" --> 0x"));
+//             cli_hexdump(buffer+idx, 1);
+               
+               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;
+}