base64.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 18 Jun 2017 01:55:49 -0400
changeset 53 ea43dbad123b
parent 0 d7ee4e2ed49d
permissions -rw-r--r--
Implemented SHA1Hmac().
icculus@0
     1
/*
icculus@0
     2
cdecoder.c - c source to a base64 decoding algorithm implementation
icculus@0
     3
icculus@0
     4
This is part of the libb64 project, and has been placed in the public domain.
icculus@0
     5
For details, see http://sourceforge.net/projects/libb64
icculus@0
     6
*/
icculus@0
     7
icculus@0
     8
#include "base64.h"
icculus@0
     9
icculus@0
    10
int base64_decode_value(char value_in)
icculus@0
    11
{
icculus@0
    12
	static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
icculus@0
    13
	static const char decoding_size = sizeof(decoding);
icculus@0
    14
	value_in -= 43;
icculus@0
    15
	if (value_in < 0 || value_in > decoding_size) return -1;
icculus@0
    16
	return decoding[(int)value_in];
icculus@0
    17
}
icculus@0
    18
icculus@0
    19
void base64_init_decodestate(base64_decodestate* state_in)
icculus@0
    20
{
icculus@0
    21
	state_in->step = step_a;
icculus@0
    22
	state_in->plainchar = 0;
icculus@0
    23
}
icculus@0
    24
icculus@0
    25
int base64_decode_block(const char* code_in, const int length_in, uint8_t* plaintext_out, base64_decodestate* state_in)
icculus@0
    26
{
icculus@0
    27
	const char* codechar = code_in;
icculus@0
    28
	uint8_t* plainchar = plaintext_out;
icculus@0
    29
	char fragment;
icculus@0
    30
	
icculus@0
    31
	*plainchar = state_in->plainchar;
icculus@0
    32
	
icculus@0
    33
	switch (state_in->step)
icculus@0
    34
	{
icculus@0
    35
		while (1)
icculus@0
    36
		{
icculus@0
    37
	case step_a:
icculus@0
    38
			do {
icculus@0
    39
				if (codechar == code_in+length_in)
icculus@0
    40
				{
icculus@0
    41
					state_in->step = step_a;
icculus@0
    42
					state_in->plainchar = *plainchar;
icculus@0
    43
					return plainchar - plaintext_out;
icculus@0
    44
				}
icculus@0
    45
				fragment = (char)base64_decode_value(*codechar++);
icculus@0
    46
			} while (fragment < 0);
icculus@0
    47
			*plainchar    = (fragment & 0x03f) << 2;
icculus@0
    48
	case step_b:
icculus@0
    49
			do {
icculus@0
    50
				if (codechar == code_in+length_in)
icculus@0
    51
				{
icculus@0
    52
					state_in->step = step_b;
icculus@0
    53
					state_in->plainchar = *plainchar;
icculus@0
    54
					return plainchar - plaintext_out;
icculus@0
    55
				}
icculus@0
    56
				fragment = (char)base64_decode_value(*codechar++);
icculus@0
    57
			} while (fragment < 0);
icculus@0
    58
			*plainchar++ |= (fragment & 0x030) >> 4;
icculus@0
    59
			*plainchar    = (fragment & 0x00f) << 4;
icculus@0
    60
	case step_c:
icculus@0
    61
			do {
icculus@0
    62
				if (codechar == code_in+length_in)
icculus@0
    63
				{
icculus@0
    64
					state_in->step = step_c;
icculus@0
    65
					state_in->plainchar = *plainchar;
icculus@0
    66
					return plainchar - plaintext_out;
icculus@0
    67
				}
icculus@0
    68
				fragment = (char)base64_decode_value(*codechar++);
icculus@0
    69
			} while (fragment < 0);
icculus@0
    70
			*plainchar++ |= (fragment & 0x03c) >> 2;
icculus@0
    71
			*plainchar    = (fragment & 0x003) << 6;
icculus@0
    72
	case step_d:
icculus@0
    73
			do {
icculus@0
    74
				if (codechar == code_in+length_in)
icculus@0
    75
				{
icculus@0
    76
					state_in->step = step_d;
icculus@0
    77
					state_in->plainchar = *plainchar;
icculus@0
    78
					return plainchar - plaintext_out;
icculus@0
    79
				}
icculus@0
    80
				fragment = (char)base64_decode_value(*codechar++);
icculus@0
    81
			} while (fragment < 0);
icculus@0
    82
			*plainchar++   |= (fragment & 0x03f);
icculus@0
    83
		}
icculus@0
    84
	}
icculus@0
    85
	/* control should not reach here */
icculus@0
    86
	return plainchar - plaintext_out;
icculus@0
    87
}
icculus@0
    88
icculus@0
    89
/*
icculus@0
    90
cencoder.c - c source to a base64 encoding algorithm implementation
icculus@0
    91
icculus@0
    92
This is part of the libb64 project, and has been placed in the public domain.
icculus@0
    93
For details, see http://sourceforge.net/projects/libb64
icculus@0
    94
*/
icculus@0
    95
icculus@0
    96
const int CHARS_PER_LINE = 72;
icculus@0
    97
icculus@0
    98
void base64_init_encodestate(base64_encodestate* state_in)
icculus@0
    99
{
icculus@0
   100
	state_in->step = step_A;
icculus@0
   101
	state_in->result = 0;
icculus@0
   102
	state_in->stepcount = 0;
icculus@0
   103
}
icculus@0
   104
icculus@0
   105
char base64_encode_value(char value_in)
icculus@0
   106
{
icculus@0
   107
	static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
icculus@0
   108
	if (value_in > 63) return '=';
icculus@0
   109
	return encoding[(int)value_in];
icculus@0
   110
}
icculus@0
   111
icculus@0
   112
int base64_encode_block(const uint8_t* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
icculus@0
   113
{
icculus@0
   114
	const uint8_t* plainchar = plaintext_in;
icculus@0
   115
	const uint8_t* const plaintextend = plaintext_in + length_in;
icculus@0
   116
	char* codechar = code_out;
icculus@0
   117
	char result;
icculus@0
   118
	uint8_t fragment;
icculus@0
   119
	
icculus@0
   120
	result = state_in->result;
icculus@0
   121
	
icculus@0
   122
	switch (state_in->step)
icculus@0
   123
	{
icculus@0
   124
		while (1)
icculus@0
   125
		{
icculus@0
   126
	case step_A:
icculus@0
   127
			if (plainchar == plaintextend)
icculus@0
   128
			{
icculus@0
   129
				state_in->result = result;
icculus@0
   130
				state_in->step = step_A;
icculus@0
   131
				return codechar - code_out;
icculus@0
   132
			}
icculus@0
   133
			fragment = *plainchar++;
icculus@0
   134
			result = (fragment & 0x0fc) >> 2;
icculus@0
   135
			*codechar++ = base64_encode_value(result);
icculus@0
   136
			result = (fragment & 0x003) << 4;
icculus@0
   137
	case step_B:
icculus@0
   138
			if (plainchar == plaintextend)
icculus@0
   139
			{
icculus@0
   140
				state_in->result = result;
icculus@0
   141
				state_in->step = step_B;
icculus@0
   142
				return codechar - code_out;
icculus@0
   143
			}
icculus@0
   144
			fragment = *plainchar++;
icculus@0
   145
			result |= (fragment & 0x0f0) >> 4;
icculus@0
   146
			*codechar++ = base64_encode_value(result);
icculus@0
   147
			result = (fragment & 0x00f) << 2;
icculus@0
   148
	case step_C:
icculus@0
   149
			if (plainchar == plaintextend)
icculus@0
   150
			{
icculus@0
   151
				state_in->result = result;
icculus@0
   152
				state_in->step = step_C;
icculus@0
   153
				return codechar - code_out;
icculus@0
   154
			}
icculus@0
   155
			fragment = *plainchar++;
icculus@0
   156
			result |= (fragment & 0x0c0) >> 6;
icculus@0
   157
			*codechar++ = base64_encode_value(result);
icculus@0
   158
			result  = (fragment & 0x03f) >> 0;
icculus@0
   159
			*codechar++ = base64_encode_value(result);
icculus@0
   160
			
icculus@0
   161
			++(state_in->stepcount);
icculus@0
   162
			if (state_in->stepcount == CHARS_PER_LINE/4)
icculus@0
   163
			{
icculus@0
   164
				*codechar++ = '\n';
icculus@0
   165
				state_in->stepcount = 0;
icculus@0
   166
			}
icculus@0
   167
		}
icculus@0
   168
	}
icculus@0
   169
	/* control should not reach here */
icculus@0
   170
	return codechar - code_out;
icculus@0
   171
}
icculus@0
   172
icculus@0
   173
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
icculus@0
   174
{
icculus@0
   175
	char* codechar = code_out;
icculus@0
   176
	
icculus@0
   177
	switch (state_in->step)
icculus@0
   178
	{
icculus@0
   179
	case step_B:
icculus@0
   180
		*codechar++ = base64_encode_value(state_in->result);
icculus@0
   181
		*codechar++ = '=';
icculus@0
   182
		*codechar++ = '=';
icculus@0
   183
		break;
icculus@0
   184
	case step_C:
icculus@0
   185
		*codechar++ = base64_encode_value(state_in->result);
icculus@0
   186
		*codechar++ = '=';
icculus@0
   187
		break;
icculus@0
   188
	case step_A:
icculus@0
   189
		break;
icculus@0
   190
	}
icculus@0
   191
	*codechar++ = '\n';
icculus@0
   192
	
icculus@0
   193
	return codechar - code_out;
icculus@0
   194
}
icculus@0
   195
icculus@0
   196
// end of base64.c ...
icculus@0
   197