LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/auth - srp_sb64.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 128 188 68.1 %
Date: 2020-10-30 04:50:48 Functions: 6 8 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2001-2012 Free Software Foundation, Inc.
       3             :  *
       4             :  * Author: Nikos Mavrogiannopoulos
       5             :  *
       6             :  * This file is part of GnuTLS.
       7             :  *
       8             :  * The GnuTLS is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public License
      10             :  * as published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * This library is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public License
      19             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      20             :  *
      21             :  */
      22             : 
      23             : #include "gnutls_int.h"
      24             : #include "errors.h"
      25             : #include <datum.h>
      26             : #include <auth/srp_passwd.h>
      27             : 
      28             : #ifdef ENABLE_SRP
      29             : 
      30             : /* this is a modified base64 for srp !!!
      31             :  * It seems that everybody makes their own base64 conversion.
      32             :  */
      33             : static const uint8_t b64table[] =
      34             :     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
      35             : 
      36             : static const uint8_t asciitable[128] = {
      37             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      38             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      39             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      40             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      41             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      42             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      43             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      44             :         0xff, 0xff, 0xff, 0xff, 0x3e, 0x3f,
      45             :         0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
      46             :         0x06, 0x07, 0x08, 0x09, 0xff, 0xff,
      47             :         0xff, 0xff, 0xff, 0xff, 0xff, 0x0a,
      48             :         0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
      49             :         0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
      50             :         0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
      51             :         0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
      52             :         0x23, 0xff, 0xff, 0xff, 0xff, 0xff,
      53             :         0xff, 0x24, 0x25, 0x26, 0x27, 0x28,
      54             :         0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
      55             :         0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
      56             :         0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
      57             :         0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff,
      58             :         0xff, 0xff
      59             : };
      60             : 
      61          13 : inline static int encode(uint8_t * result, const uint8_t * rdata, unsigned left)
      62             : {
      63             : 
      64          13 :         int data_len;
      65          13 :         int c, ret = 4;
      66          13 :         uint8_t data[3];
      67             : 
      68          13 :         if (left > 3)
      69             :                 data_len = 3;
      70             :         else
      71           4 :                 data_len = left;
      72             : 
      73          13 :         data[0] = data[1] = data[2] = 0;
      74          13 :         memcpy(data, rdata, data_len);
      75             : 
      76          13 :         switch (data_len) {
      77          11 :         case 3:
      78          11 :                 result[0] = b64table[((data[0] & 0xfc) >> 2)];
      79          11 :                 result[1] =
      80          11 :                     b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) |
      81          11 :                               ((data[1] & 0xf0) >> 4))];
      82          11 :                 result[2] =
      83          11 :                     b64table[((((data[1] & 0x0f) << 2) & 0xff) |
      84          11 :                               ((data[2] & 0xc0) >> 6))];
      85          11 :                 result[3] = b64table[(data[2] & 0x3f) & 0xff];
      86          11 :                 break;
      87           0 :         case 2:
      88           0 :                 if ((c = ((data[0] & 0xf0) >> 4)) != 0) {
      89           0 :                         result[0] = b64table[c];
      90           0 :                         result[1] =
      91           0 :                             b64table[((((data[0] & 0x0f) << 2) & 0xff) |
      92           0 :                                       ((data[1] & 0xc0) >> 6))];
      93           0 :                         result[2] = b64table[(data[1] & 0x3f) & 0xff];
      94           0 :                         result[3] = '\0';
      95           0 :                         ret -= 1;
      96             :                 } else {
      97           0 :                         if ((c =
      98           0 :                              ((data[0] & 0x0f) << 2) | ((data[1] & 0xc0) >>
      99             :                                                         6)) != 0) {
     100           0 :                                 result[0] = b64table[c];
     101           0 :                                 result[1] = b64table[data[1] & 0x3f];
     102           0 :                                 result[2] = '\0';
     103           0 :                                 result[3] = '\0';
     104           0 :                                 ret -= 2;
     105             :                         } else {
     106           0 :                                 result[0] = b64table[data[0] & 0x3f];
     107           0 :                                 result[1] = '\0';
     108           0 :                                 result[2] = '\0';
     109           0 :                                 result[3] = '\0';
     110           0 :                                 ret -= 3;
     111             :                         }
     112             :                 }
     113             :                 break;
     114           2 :         case 1:
     115           2 :                 if ((c = ((data[0] & 0xc0) >> 6)) != 0) {
     116           1 :                         result[0] = b64table[c];
     117           1 :                         result[1] = b64table[(data[0] & 0x3f) & 0xff];
     118           1 :                         result[2] = '\0';
     119           1 :                         result[3] = '\0';
     120           1 :                         ret -= 2;
     121             :                 } else {
     122           1 :                         result[0] = b64table[(data[0] & 0x3f) & 0xff];
     123           1 :                         result[1] = '\0';
     124           1 :                         result[2] = '\0';
     125           1 :                         result[3] = '\0';
     126           1 :                         ret -= 3;
     127             :                 }
     128             :                 break;
     129             :         default:
     130             :                 return GNUTLS_E_BASE64_ENCODING_ERROR;
     131             :         }
     132             : 
     133             :         return ret;
     134             : 
     135             : }
     136             : 
     137             : /* encodes data and puts the result into result (locally allocated)
     138             :  * The result_size is the return value
     139             :  */
     140             : static int
     141           2 : _gnutls_sbase64_encode(uint8_t * data, size_t data_size, char **result)
     142             : {
     143           2 :         unsigned i, j;
     144           2 :         int ret, tmp;
     145           2 :         uint8_t tmpres[4];
     146           2 :         unsigned mod = data_size % 3;
     147             : 
     148           2 :         ret = mod;
     149           2 :         if (ret != 0)
     150             :                 ret = 4;
     151             :         else
     152           0 :                 ret = 0;
     153             : 
     154           2 :         ret += (data_size * 4) / 3;
     155             : 
     156           2 :         (*result) = gnutls_calloc(1, ret + 1);
     157           2 :         if ((*result) == NULL)
     158             :                 return GNUTLS_E_MEMORY_ERROR;
     159             : 
     160           2 :         i = j = 0;
     161             : /* encode the bytes that are not a multiple of 3 
     162             :  */
     163           2 :         if (mod > 0) {
     164           2 :                 tmp = encode(tmpres, &data[0], mod);
     165           2 :                 if (tmp < 0) {
     166           0 :                         gnutls_free((*result));
     167           0 :                         return tmp;
     168             :                 }
     169             : 
     170           2 :                 memcpy(&(*result)[0], tmpres, tmp);
     171           2 :                 i = mod;
     172           2 :                 j = tmp;
     173             : 
     174             :         }
     175             : /* encode the rest
     176             :  */
     177          13 :         for (; i < data_size; i += 3, j += 4) {
     178          11 :                 tmp = encode(tmpres, &data[i], data_size - i);
     179          11 :                 if (tmp < 0) {
     180           0 :                         gnutls_free((*result));
     181           0 :                         return tmp;
     182             :                 }
     183          11 :                 memcpy(&(*result)[j], tmpres, tmp);
     184             :         }
     185             : 
     186           2 :         return strlen(*result);
     187             : }
     188             : 
     189             : 
     190             : /* data must be 4 bytes
     191             :  * result should be 3 bytes
     192             :  */
     193             : #define TOASCII(c) (c < 127 ? asciitable[c] : 0xff)
     194        3856 : inline static int decode(uint8_t * result, const uint8_t * data)
     195             : {
     196        3856 :         uint8_t a1, a2;
     197        3856 :         int ret = 3;
     198             : 
     199        3856 :         memset(result, 0, 3);
     200             : 
     201        3856 :         a1 = TOASCII(data[3]);
     202        3856 :         a2 = TOASCII(data[2]);
     203        3856 :         if (a1 != 0xff)
     204        3855 :                 result[2] = a1 & 0xff;
     205             :         else
     206             :                 return GNUTLS_E_BASE64_DECODING_ERROR;
     207        3855 :         if (a2 != 0xff)
     208        3841 :                 result[2] |= ((a2 & 0x03) << 6) & 0xff;
     209             : 
     210        3855 :         a1 = a2;
     211        3855 :         a2 = TOASCII(data[1]);
     212        3855 :         if (a1 != 0xff)
     213        3841 :                 result[1] = ((a1 & 0x3c) >> 2);
     214        3855 :         if (a2 != 0xff)
     215        3809 :                 result[1] |= ((a2 & 0x0f) << 4);
     216          46 :         else if (a1 == 0xff || result[1] == 0)
     217          46 :                 ret--;
     218             : 
     219        3855 :         a1 = a2;
     220        3855 :         a2 = TOASCII(data[0]);
     221        3855 :         if (a1 != 0xff)
     222        3809 :                 result[0] = (((a1 & 0x30) >> 4) & 0xff);
     223        3855 :         if (a2 != 0xff)
     224        3759 :                 result[0] |= ((a2 << 2) & 0xff);
     225          96 :         else if (a1 == 0xff || result[0] == 0)
     226          96 :                 ret--;
     227             : 
     228             :         return ret;
     229             : }
     230             : 
     231             : /* decodes data and puts the result into result (locally allocated)
     232             :  * The result_size is the return value.
     233             :  * That function does not ignore newlines tabs etc. You should remove them
     234             :  * before calling it.
     235             :  */
     236             : int
     237         101 : _gnutls_sbase64_decode(char *data, size_t idata_size, uint8_t ** result)
     238             : {
     239         101 :         unsigned i, j;
     240         101 :         int ret, left;
     241         101 :         int data_size, tmp;
     242         101 :         uint8_t datrev[4];
     243         101 :         uint8_t tmpres[3];
     244             : 
     245         101 :         data_size = (idata_size / 4) * 4;
     246         101 :         left = idata_size % 4;
     247             : 
     248         101 :         ret = (data_size / 4) * 3;
     249             : 
     250         101 :         if (left > 0)
     251          97 :                 ret += 3;
     252             : 
     253         101 :         (*result) = gnutls_malloc(ret + 1);
     254         101 :         if ((*result) == NULL)
     255             :                 return GNUTLS_E_MEMORY_ERROR;
     256             : 
     257             :         /* the first "block" is treated with special care */
     258         101 :         tmp = 0;
     259         101 :         if (left > 0) {
     260          97 :                 memset(datrev, 0, 4);
     261          97 :                 memcpy(&datrev[4 - left], data, left);
     262             : 
     263          97 :                 tmp = decode(tmpres, datrev);
     264          97 :                 if (tmp < 0) {
     265           1 :                         gnutls_free((*result));
     266           1 :                         return tmp;
     267             :                 }
     268             : 
     269          96 :                 memcpy(*result, &tmpres[3 - tmp], tmp);
     270          96 :                 if (tmp < 3)
     271          96 :                         ret -= (3 - tmp);
     272             :         }
     273             : 
     274             :         /* rest data */
     275        3859 :         for (i = left, j = tmp; i < idata_size; i += 4) {
     276        3759 :                 tmp = decode(tmpres, (uint8_t *) & data[i]);
     277        3759 :                 if (tmp < 0) {
     278           0 :                         gnutls_free((*result));
     279           0 :                         return tmp;
     280             :                 }
     281        3759 :                 memcpy(&(*result)[j], tmpres, tmp);
     282        3759 :                 if (tmp < 3)
     283           0 :                         ret -= (3 - tmp);
     284        3759 :                 j += 3;
     285             :         }
     286             : 
     287             :         return ret;
     288             : }
     289             : 
     290             : /**
     291             :  * gnutls_srp_base64_encode:
     292             :  * @data: contain the raw data
     293             :  * @result: the place where base64 data will be copied
     294             :  * @result_size: holds the size of the result
     295             :  *
     296             :  * This function will convert the given data to printable data, using
     297             :  * the base64 encoding, as used in the libsrp.  This is the encoding
     298             :  * used in SRP password files.  If the provided buffer is not long
     299             :  * enough GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
     300             :  *
     301             :  * Warning!  This base64 encoding is not the "standard" encoding, so
     302             :  * do not use it for non-SRP purposes.
     303             :  *
     304             :  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
     305             :  * long enough, or 0 on success.
     306             :  **/
     307             : int
     308           0 : gnutls_srp_base64_encode(const gnutls_datum_t * data, char *result,
     309             :                          size_t * result_size)
     310             : {
     311           0 :         char *res;
     312           0 :         int size;
     313             : 
     314           0 :         size = _gnutls_sbase64_encode(data->data, data->size, &res);
     315           0 :         if (size < 0)
     316             :                 return size;
     317             : 
     318           0 :         if (result == NULL || *result_size < (size_t) size) {
     319           0 :                 gnutls_free(res);
     320           0 :                 *result_size = size;
     321           0 :                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
     322             :         } else {
     323           0 :                 memcpy(result, res, size);
     324           0 :                 gnutls_free(res);
     325           0 :                 *result_size = size;
     326             :         }
     327             : 
     328           0 :         return 0;
     329             : }
     330             : 
     331             : /**
     332             :  * gnutls_srp_base64_encode2:
     333             :  * @data: contains the raw data
     334             :  * @result: will hold the newly allocated encoded data
     335             :  *
     336             :  * This function will convert the given data to printable data, using
     337             :  * the base64 encoding.  This is the encoding used in SRP password
     338             :  * files.  This function will allocate the required memory to hold
     339             :  * the encoded data.
     340             :  *
     341             :  * You should use gnutls_free() to free the returned data.
     342             :  *
     343             :  * Warning!  This base64 encoding is not the "standard" encoding, so
     344             :  * do not use it for non-SRP purposes.
     345             :  *
     346             :  * Returns: 0 on success, or an error code.
     347             :  **/
     348             : int
     349           2 : gnutls_srp_base64_encode2(const gnutls_datum_t * data,
     350             :                                gnutls_datum_t * result)
     351             : {
     352           2 :         char *res;
     353           2 :         int size;
     354             : 
     355           2 :         size = _gnutls_sbase64_encode(data->data, data->size, &res);
     356           2 :         if (size < 0)
     357             :                 return size;
     358             : 
     359           2 :         if (result == NULL) {
     360           0 :                 gnutls_free(res);
     361           0 :                 return GNUTLS_E_INVALID_REQUEST;
     362             :         } else {
     363           2 :                 result->data = (uint8_t *) res;
     364           2 :                 result->size = size;
     365             :         }
     366             : 
     367           2 :         return 0;
     368             : }
     369             : 
     370             : /**
     371             :  * gnutls_srp_base64_decode:
     372             :  * @b64_data: contain the encoded data
     373             :  * @result: the place where decoded data will be copied
     374             :  * @result_size: holds the size of the result
     375             :  *
     376             :  * This function will decode the given encoded data, using the base64
     377             :  * encoding found in libsrp.
     378             :  *
     379             :  * Note that @b64_data should be null terminated.
     380             :  *
     381             :  * Warning!  This base64 encoding is not the "standard" encoding, so
     382             :  * do not use it for non-SRP purposes.
     383             :  *
     384             :  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
     385             :  * long enough, or 0 on success.
     386             :  **/
     387             : int
     388           0 : gnutls_srp_base64_decode(const gnutls_datum_t * b64_data, char *result,
     389             :                          size_t * result_size)
     390             : {
     391           0 :         uint8_t *res;
     392           0 :         int size;
     393             : 
     394           0 :         size =
     395           0 :             _gnutls_sbase64_decode((char *) b64_data->data, b64_data->size,
     396             :                                    &res);
     397           0 :         if (size < 0)
     398             :                 return size;
     399             : 
     400           0 :         if (result == NULL || *result_size < (size_t) size) {
     401           0 :                 gnutls_free(res);
     402           0 :                 *result_size = size;
     403           0 :                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
     404             :         } else {
     405           0 :                 memcpy(result, res, size);
     406           0 :                 gnutls_free(res);
     407           0 :                 *result_size = size;
     408             :         }
     409             : 
     410           0 :         return 0;
     411             : }
     412             : 
     413             : /**
     414             :  * gnutls_srp_base64_decode2:
     415             :  * @b64_data: contains the encoded data
     416             :  * @result: the place where decoded data lie
     417             :  *
     418             :  * This function will decode the given encoded data. The decoded data
     419             :  * will be allocated, and stored into result.  It will decode using
     420             :  * the base64 algorithm as used in libsrp.
     421             :  *
     422             :  * You should use gnutls_free() to free the returned data.
     423             :  *
     424             :  * Warning!  This base64 encoding is not the "standard" encoding, so
     425             :  * do not use it for non-SRP purposes.
     426             :  *
     427             :  * Returns: 0 on success, or an error code.
     428             :  **/
     429             : int
     430          65 : gnutls_srp_base64_decode2(const gnutls_datum_t * b64_data,
     431             :                                gnutls_datum_t * result)
     432             : {
     433          65 :         uint8_t *ret;
     434          65 :         int size;
     435             : 
     436          65 :         size =
     437          65 :             _gnutls_sbase64_decode((char *) b64_data->data, b64_data->size,
     438             :                                    &ret);
     439          65 :         if (size < 0)
     440             :                 return size;
     441             : 
     442          64 :         if (result == NULL) {
     443           0 :                 gnutls_free(ret);
     444           0 :                 return GNUTLS_E_INVALID_REQUEST;
     445             :         } else {
     446          64 :                 result->data = ret;
     447          64 :                 result->size = size;
     448             :         }
     449             : 
     450          64 :         return 0;
     451             : }
     452             : 
     453             : #endif                          /* ENABLE_SRP */

Generated by: LCOV version 1.14