CyaSSL is an SSL library for devices like mbed.

Dependents:   cyassl-client Sync

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-2009 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 
00023 #include "coding.h"
00024 
00025 
00026 enum {
00027     BAD         = 0xFF,  /* invalid encoding */
00028     PAD         = '=',
00029     PEM_LINE_SZ = 64
00030 };
00031 
00032 
00033 static
00034 const byte base64Decode[] = { 62, BAD, BAD, BAD, 63,   /* + starts at 0x2B */
00035                               52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
00036                               BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00037                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00038                               10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
00039                               20, 21, 22, 23, 24, 25,
00040                               BAD, BAD, BAD, BAD, BAD, BAD,
00041                               26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
00042                               36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
00043                               46, 47, 48, 49, 50, 51
00044                             };
00045 
00046 
00047 int Base64Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
00048 {
00049     word32 i = 0;
00050     word32 j = 0;
00051     word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
00052 
00053     plainSz = (plainSz * 3 + 3) / 4;
00054     if (plainSz > *outLen) return -1;
00055 
00056     while (inLen > 3) {
00057         byte b1, b2, b3;
00058         byte e1 = in[j++];
00059         byte e2 = in[j++];
00060         byte e3 = in[j++];
00061         byte e4 = in[j++];
00062 
00063         int pad3 = 0;
00064         int pad4 = 0;
00065 
00066         if (e1 == 0)            /* end file 0's */
00067             break;
00068         if (e3 == PAD)
00069             pad3 = 1;
00070         if (e4 == PAD)
00071             pad4 = 1;
00072 
00073         e1 = base64Decode[e1 - 0x2B];
00074         e2 = base64Decode[e2 - 0x2B];
00075         e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];
00076         e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];
00077 
00078         b1 = (e1 << 2) | (e2 >> 4);
00079         b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
00080         b3 = ((e3 & 0x3) << 6) | e4;
00081 
00082         out[i++] = b1;
00083         if (!pad3)
00084             out[i++] = b2;
00085         if (!pad4)
00086             out[i++] = b3;
00087         else
00088             break;
00089         
00090         inLen -= 4;
00091         if (in[j] == ' ' || in[j] == '\r' || in[j] == '\n') {
00092             byte endLine = in[j++];
00093             inLen--;
00094             while (endLine == ' ') {   /* allow trailing whitespace */
00095                 endLine = in[j++];
00096                 inLen--;
00097             }
00098             if (endLine == '\r') {
00099                 endLine = in[j++];
00100                 inLen--;
00101             }
00102             if (endLine != '\n')
00103                 return -1;
00104         }
00105     }
00106     *outLen = i;
00107 
00108     return 0;
00109 }
00110 
00111 
00112 #if defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN)
00113 
00114 static
00115 const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00116                               'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00117                               'U', 'V', 'W', 'X', 'Y', 'Z',
00118                               'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
00119                               'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
00120                               'u', 'v', 'w', 'x', 'y', 'z',
00121                               '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00122                               '+', '/'
00123                             };
00124 
00125 
00126 /* porting assistance from yaSSL by Raphael HUCK */
00127 int Base64Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
00128 {
00129     word32 i = 0,
00130            j = 0,
00131            n = 0;   /* new line counter */
00132 
00133     word32 outSz = (inLen + 3 - 1) / 3 * 4;
00134     outSz += (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
00135 
00136     if (outSz > *outLen) return -1;
00137     
00138     while (inLen > 2) {
00139         byte b1 = in[j++];
00140         byte b2 = in[j++];
00141         byte b3 = in[j++];
00142 
00143         /* encoded idx */
00144         byte e1 = b1 >> 2;
00145         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
00146         byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
00147         byte e4 = b3 & 0x3F;
00148 
00149         /* store */
00150         out[i++] = base64Encode[e1];
00151         out[i++] = base64Encode[e2];
00152         out[i++] = base64Encode[e3];
00153         out[i++] = base64Encode[e4];
00154 
00155         inLen -= 3;
00156 
00157         if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen)
00158             out[i++] = '\n';
00159     }
00160 
00161     /* last integral */
00162     if (inLen) {
00163         int twoBytes = (inLen == 2);
00164 
00165         byte b1 = in[j++];
00166         byte b2 = (twoBytes) ? in[j++] : 0;
00167 
00168         byte e1 = b1 >> 2;
00169         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
00170         byte e3 =  (b2 & 0xF) << 2;
00171 
00172         out[i++] = base64Encode[e1];
00173         out[i++] = base64Encode[e2];
00174         out[i++] = (twoBytes) ? base64Encode[e3] : PAD;
00175         out[i++] = PAD;
00176     } 
00177 
00178     out[i++] = '\n';
00179     if (i != outSz)
00180         return -1;
00181     *outLen = outSz;
00182 
00183     return 0; 
00184 }
00185 
00186 
00187 static
00188 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00189                            BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00190                            10, 11, 12, 13, 14, 15 
00191                          };  /* A starts at 0x41 not 0x3A */
00192 
00193 int Base16Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
00194 {
00195     word32 inIdx  = 0;
00196     word32 outIdx = 0;
00197 
00198     if (inLen % 2)
00199         return -1;
00200 
00201     if (*outLen < (inLen / 2))
00202         return -1;
00203 
00204     while (inLen) {
00205         byte b  = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
00206         byte b2 = in[inIdx++] - 0x30;
00207 
00208         /* sanity checks */
00209         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
00210             return -1;
00211         if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
00212             return -1;
00213 
00214         b  = hexDecode[b];
00215         b2 = hexDecode[b2];
00216 
00217         if (b == BAD || b2 == BAD)
00218             return -1;
00219         
00220         out[outIdx++] = (b << 4) | b2;
00221         inLen -= 2;
00222     }
00223 
00224     *outLen = outIdx;
00225     return 0;
00226 }
00227 
00228 
00229 #endif  /* OPENSSL_EXTRA */