cyassl re-port with cellular comms, PSK test

Dependencies:   VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src

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 <cyassl/ctaocrypt/coding.h>
00027 #include <cyassl/ctaocrypt/error.h>
00028 #include <cyassl/ctaocrypt/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 #if defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER)
00131 
00132 static
00133 const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00134                               'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00135                               'U', 'V', 'W', 'X', 'Y', 'Z',
00136                               'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
00137                               'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
00138                               'u', 'v', 'w', 'x', 'y', 'z',
00139                               '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00140                               '+', '/'
00141                             };
00142 
00143 
00144 /* porting assistance from yaSSL by Raphael HUCK */
00145 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
00146 {
00147     word32 i = 0,
00148            j = 0,
00149            n = 0;   /* new line counter */
00150 
00151     word32 outSz = (inLen + 3 - 1) / 3 * 4;
00152     outSz += (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
00153 
00154     if (outSz > *outLen) return BAD_FUNC_ARG;
00155     
00156     while (inLen > 2) {
00157         byte b1 = in[j++];
00158         byte b2 = in[j++];
00159         byte b3 = in[j++];
00160 
00161         /* encoded idx */
00162         byte e1 = b1 >> 2;
00163         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
00164         byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
00165         byte e4 = b3 & 0x3F;
00166 
00167         /* store */
00168         out[i++] = base64Encode[e1];
00169         out[i++] = base64Encode[e2];
00170         out[i++] = base64Encode[e3];
00171         out[i++] = base64Encode[e4];
00172 
00173         inLen -= 3;
00174 
00175         if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen)
00176             out[i++] = '\n';
00177     }
00178 
00179     /* last integral */
00180     if (inLen) {
00181         int twoBytes = (inLen == 2);
00182 
00183         byte b1 = in[j++];
00184         byte b2 = (twoBytes) ? in[j++] : 0;
00185 
00186         byte e1 = b1 >> 2;
00187         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
00188         byte e3 =  (b2 & 0xF) << 2;
00189 
00190         out[i++] = base64Encode[e1];
00191         out[i++] = base64Encode[e2];
00192         out[i++] = (twoBytes) ? base64Encode[e3] : PAD;
00193         out[i++] = PAD;
00194     } 
00195 
00196     out[i++] = '\n';
00197     if (i != outSz)
00198         return ASN_INPUT_E; 
00199     *outLen = outSz;
00200 
00201     return 0; 
00202 }
00203 
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) */