A simple CyaSSL-based HMAC-MD5 implementation. Licensed under GPL v2.

Dependents:   RFrec_full RFtrans_full

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers coding.c Source File

coding.c

00001 /* coding.c
00002  *
00003  * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023     #include <config.h>
00024 #endif
00025 
00026 #include "coding.h"
00027 #include "error.h"
00028 //#include "logging.h"
00029 
00030 
00031 enum {
00032     BAD         = 0xFF,  /* invalid encoding */
00033     PAD         = '=',
00034     PEM_LINE_SZ = 64
00035 };
00036 
00037 
00038 static
00039 const byte base64Decode[] = { 62, BAD, BAD, BAD, 63,   /* + starts at 0x2B */
00040                               52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
00041                               BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00042                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00043                               10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
00044                               20, 21, 22, 23, 24, 25,
00045                               BAD, BAD, BAD, BAD, BAD, BAD,
00046                               26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
00047                               36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
00048                               46, 47, 48, 49, 50, 51
00049                             };
00050 
00051 
00052 int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
00053 {
00054     word32 i = 0;
00055     word32 j = 0;
00056     word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
00057     const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
00058 
00059     plainSz = (plainSz * 3 + 3) / 4;
00060     if (plainSz > *outLen) return BAD_FUNC_ARG;
00061 
00062     while (inLen > 3) {
00063         byte b1, b2, b3;
00064         byte e1 = in[j++];
00065         byte e2 = in[j++];
00066         byte e3 = in[j++];
00067         byte e4 = in[j++];
00068 
00069         int pad3 = 0;
00070         int pad4 = 0;
00071 
00072         if (e1 == 0)            /* end file 0's */
00073             break;
00074         if (e3 == PAD)
00075             pad3 = 1;
00076         if (e4 == PAD)
00077             pad4 = 1;
00078 
00079         if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
00080   //          CYASSL_MSG("Bad Base64 Decode data, too small");
00081             return ASN_INPUT_E;
00082         }
00083 
00084         if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
00085   //          CYASSL_MSG("Bad Base64 Decode data, too big");
00086             return ASN_INPUT_E;
00087         }
00088 
00089         e1 = base64Decode[e1 - 0x2B];
00090         e2 = base64Decode[e2 - 0x2B];
00091         e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];
00092         e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];
00093 
00094         b1 = (e1 << 2) | (e2 >> 4);
00095         b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
00096         b3 = ((e3 & 0x3) << 6) | e4;
00097 
00098         out[i++] = b1;
00099         if (!pad3)
00100             out[i++] = b2;
00101         if (!pad4)
00102             out[i++] = b3;
00103         else
00104             break;
00105         
00106         inLen -= 4;
00107         if (in[j] == ' ' || in[j] == '\r' || in[j] == '\n') {
00108             byte endLine = in[j++];
00109             inLen--;
00110             while (endLine == ' ') {   /* allow trailing whitespace */
00111                 endLine = in[j++];
00112                 inLen--;
00113             }
00114             if (endLine == '\r') {
00115                 endLine = in[j++];
00116                 inLen--;
00117             }
00118             if (endLine != '\n') {
00119   //              CYASSL_MSG("Bad end of line in Base64 Decode");
00120                 return ASN_INPUT_E;
00121             }
00122         }
00123     }
00124     *outLen = i;
00125 
00126     return 0;
00127 }
00128 
00129 
00130 
00131 static
00132 const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00133                               'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00134                               'U', 'V', 'W', 'X', 'Y', 'Z',
00135                               'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
00136                               'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
00137                               'u', 'v', 'w', 'x', 'y', 'z',
00138                               '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00139                               '+', '/'
00140                             };
00141 
00142 
00143 /* porting assistance from yaSSL by Raphael HUCK */
00144 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
00145 {
00146     word32 i = 0,
00147            j = 0,
00148            n = 0;   /* new line counter */
00149 
00150     word32 outSz = (inLen + 3 - 1) / 3 * 4;
00151     outSz += (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
00152 
00153     if (outSz > *outLen) return BAD_FUNC_ARG;
00154     
00155     while (inLen > 2) {
00156         byte b1 = in[j++];
00157         byte b2 = in[j++];
00158         byte b3 = in[j++];
00159 
00160         /* encoded idx */
00161         byte e1 = b1 >> 2;
00162         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
00163         byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
00164         byte e4 = b3 & 0x3F;
00165 
00166         /* store */
00167         out[i++] = base64Encode[e1];
00168         out[i++] = base64Encode[e2];
00169         out[i++] = base64Encode[e3];
00170         out[i++] = base64Encode[e4];
00171 
00172         inLen -= 3;
00173 
00174         if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen)
00175             out[i++] = '\n';
00176     }
00177 
00178     /* last integral */
00179     if (inLen) {
00180         int twoBytes = (inLen == 2);
00181 
00182         byte b1 = in[j++];
00183         byte b2 = (twoBytes) ? in[j++] : 0;
00184 
00185         byte e1 = b1 >> 2;
00186         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
00187         byte e3 =  (b2 & 0xF) << 2;
00188 
00189         out[i++] = base64Encode[e1];
00190         out[i++] = base64Encode[e2];
00191         out[i++] = (twoBytes) ? base64Encode[e3] : PAD;
00192         out[i++] = PAD;
00193     } 
00194 
00195     out[i++] = '\n';
00196     if (i != outSz)
00197         return ASN_INPUT_E; 
00198     *outLen = outSz;
00199 
00200     return 0; 
00201 }
00202 
00203 #if defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER)
00204 
00205 static
00206 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00207                            BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00208                            10, 11, 12, 13, 14, 15 
00209                          };  /* A starts at 0x41 not 0x3A */
00210 
00211 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
00212 {
00213     word32 inIdx  = 0;
00214     word32 outIdx = 0;
00215 
00216     if (inLen == 1 && *outLen && in) {
00217         byte b = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
00218 
00219         /* sanity check */
00220         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
00221             return ASN_INPUT_E;
00222 
00223         b  = hexDecode[b];
00224 
00225         if (b == BAD)
00226             return ASN_INPUT_E;
00227         
00228         out[outIdx++] = b;
00229 
00230         *outLen = outIdx;
00231         return 0;
00232     }
00233 
00234     if (inLen % 2)
00235         return BAD_FUNC_ARG;
00236 
00237     if (*outLen < (inLen / 2))
00238         return BAD_FUNC_ARG;
00239 
00240     while (inLen) {
00241         byte b  = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
00242         byte b2 = in[inIdx++] - 0x30;
00243 
00244         /* sanity checks */
00245         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
00246             return ASN_INPUT_E;
00247         if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
00248             return ASN_INPUT_E;
00249 
00250         b  = hexDecode[b];
00251         b2 = hexDecode[b2];
00252 
00253         if (b == BAD || b2 == BAD)
00254             return ASN_INPUT_E;
00255         
00256         out[outIdx++] = (b << 4) | b2;
00257         inLen -= 2;
00258     }
00259 
00260     *outLen = outIdx;
00261     return 0;
00262 }
00263 
00264 
00265 #endif  /* defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER) */