Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
c-utility/src/base32.c@0:f7f1f0d76dd6, 2018-08-23 (annotated)
- Committer:
- XinZhangMS
- Date:
- Thu Aug 23 06:52:14 2018 +0000
- Revision:
- 0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| XinZhangMS | 0:f7f1f0d76dd6 | 1 | // Copyright (c) Microsoft. All rights reserved. |
| XinZhangMS | 0:f7f1f0d76dd6 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
| XinZhangMS | 0:f7f1f0d76dd6 | 3 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 4 | #include <stdlib.h> |
| XinZhangMS | 0:f7f1f0d76dd6 | 5 | #include <stddef.h> |
| XinZhangMS | 0:f7f1f0d76dd6 | 6 | #include <stdint.h> |
| XinZhangMS | 0:f7f1f0d76dd6 | 7 | #include <ctype.h> |
| XinZhangMS | 0:f7f1f0d76dd6 | 8 | #include "azure_c_shared_utility/buffer_.h" |
| XinZhangMS | 0:f7f1f0d76dd6 | 9 | #include "azure_c_shared_utility/xlogging.h" |
| XinZhangMS | 0:f7f1f0d76dd6 | 10 | #include "azure_c_shared_utility/gballoc.h" |
| XinZhangMS | 0:f7f1f0d76dd6 | 11 | #include "azure_c_shared_utility/strings.h" |
| XinZhangMS | 0:f7f1f0d76dd6 | 12 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 13 | #include "azure_c_shared_utility/base32.h" |
| XinZhangMS | 0:f7f1f0d76dd6 | 14 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 15 | static const unsigned char BASE32_EQUAL_SIGN = 32; |
| XinZhangMS | 0:f7f1f0d76dd6 | 16 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 17 | static const char BASE32_VALUES[] = "abcdefghijklmnopqrstuvwxyz234567="; |
| XinZhangMS | 0:f7f1f0d76dd6 | 18 | #define TARGET_BLOCK_SIZE 5 |
| XinZhangMS | 0:f7f1f0d76dd6 | 19 | #define INVALID_CHAR_POS 260 |
| XinZhangMS | 0:f7f1f0d76dd6 | 20 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 21 | #define BASE32_INPUT_SIZE 8 |
| XinZhangMS | 0:f7f1f0d76dd6 | 22 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 23 | #define ASCII_VALUE_MAX 0x80 |
| XinZhangMS | 0:f7f1f0d76dd6 | 24 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 25 | static size_t base32_encoding_length(size_t src_len) |
| XinZhangMS | 0:f7f1f0d76dd6 | 26 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 27 | return (((src_len + TARGET_BLOCK_SIZE - 1) / TARGET_BLOCK_SIZE) * 8); |
| XinZhangMS | 0:f7f1f0d76dd6 | 28 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 29 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 30 | static size_t base32_decoding_length(size_t src_len) |
| XinZhangMS | 0:f7f1f0d76dd6 | 31 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 32 | return ((src_len*TARGET_BLOCK_SIZE) / 8); |
| XinZhangMS | 0:f7f1f0d76dd6 | 33 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 34 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 35 | static unsigned char convert_value_to_base32_char(unsigned char value) |
| XinZhangMS | 0:f7f1f0d76dd6 | 36 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 37 | unsigned char result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 38 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 39 | if (value >= 50 && value <= 55) |
| XinZhangMS | 0:f7f1f0d76dd6 | 40 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 41 | result = 0x1a+(value-50); |
| XinZhangMS | 0:f7f1f0d76dd6 | 42 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 43 | else if (value == 61) |
| XinZhangMS | 0:f7f1f0d76dd6 | 44 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 45 | result = 0x20; |
| XinZhangMS | 0:f7f1f0d76dd6 | 46 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 47 | else if ((value <= 49) || (value >= 56 && value <= 64)) |
| XinZhangMS | 0:f7f1f0d76dd6 | 48 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 49 | result = 0xFF; |
| XinZhangMS | 0:f7f1f0d76dd6 | 50 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 51 | else if (value >= 65 && value <= 90) |
| XinZhangMS | 0:f7f1f0d76dd6 | 52 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 53 | result = 0x00 + (value - 65); |
| XinZhangMS | 0:f7f1f0d76dd6 | 54 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 55 | else if (value >= 91 && value <= 96) |
| XinZhangMS | 0:f7f1f0d76dd6 | 56 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 57 | result = 0xFF; |
| XinZhangMS | 0:f7f1f0d76dd6 | 58 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 59 | else if (value >= 97 && value <= 123) |
| XinZhangMS | 0:f7f1f0d76dd6 | 60 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 61 | result = 0x00 + (value - 97); |
| XinZhangMS | 0:f7f1f0d76dd6 | 62 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 63 | else // value > 123 |
| XinZhangMS | 0:f7f1f0d76dd6 | 64 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 65 | result = 0xFF; |
| XinZhangMS | 0:f7f1f0d76dd6 | 66 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 67 | return result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 68 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 69 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 70 | static char* base32_encode_impl(const unsigned char* source, size_t src_size) |
| XinZhangMS | 0:f7f1f0d76dd6 | 71 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 72 | char* result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 73 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 74 | // Allocate target buffer |
| XinZhangMS | 0:f7f1f0d76dd6 | 75 | size_t output_len = base32_encoding_length(src_size); |
| XinZhangMS | 0:f7f1f0d76dd6 | 76 | /* Codes_SRS_BASE32_07_009: [ base32_encode_impl shall allocate the buffer to the size of the encoding value. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 77 | if ((result = (char*)malloc(output_len + 1)) == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 78 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 79 | LogError("Failure allocating output buffer"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 80 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 81 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 82 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 83 | const unsigned char* iterator = source; |
| XinZhangMS | 0:f7f1f0d76dd6 | 84 | size_t block_len = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 85 | size_t result_len = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 86 | unsigned char pos1 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 87 | unsigned char pos2 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 88 | unsigned char pos3 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 89 | unsigned char pos4 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 90 | unsigned char pos5 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 91 | unsigned char pos6 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 92 | unsigned char pos7 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 93 | unsigned char pos8 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 94 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 95 | memset(result, 0, output_len + 1); |
| XinZhangMS | 0:f7f1f0d76dd6 | 96 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 97 | // Go through the source buffer sectioning off blocks of 5 |
| XinZhangMS | 0:f7f1f0d76dd6 | 98 | /* Codes_SRS_BASE32_07_010: [ base32_encode_impl shall look through source and separate each block into 5 bit chunks ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 99 | while (src_size >= 1 && result != NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 100 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 101 | pos1 = pos2 = pos3 = pos4 = pos5 = pos6 = pos7 = pos8 = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 102 | block_len = src_size > TARGET_BLOCK_SIZE ? TARGET_BLOCK_SIZE : src_size; |
| XinZhangMS | 0:f7f1f0d76dd6 | 103 | // Fall through switch block to process the 5 (or smaller) block |
| XinZhangMS | 0:f7f1f0d76dd6 | 104 | switch (block_len) |
| XinZhangMS | 0:f7f1f0d76dd6 | 105 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 106 | case 5: |
| XinZhangMS | 0:f7f1f0d76dd6 | 107 | pos8 = (iterator[4] & 0x1f); |
| XinZhangMS | 0:f7f1f0d76dd6 | 108 | pos7 = ((iterator[4] & 0xe0) >> 5); |
| XinZhangMS | 0:f7f1f0d76dd6 | 109 | // fall through |
| XinZhangMS | 0:f7f1f0d76dd6 | 110 | case 4: |
| XinZhangMS | 0:f7f1f0d76dd6 | 111 | pos7 |= ((iterator[3] & 0x03) << 3); |
| XinZhangMS | 0:f7f1f0d76dd6 | 112 | pos6 = ((iterator[3] & 0x7c) >> 2); |
| XinZhangMS | 0:f7f1f0d76dd6 | 113 | pos5 = ((iterator[3] & 0x80) >> 7); |
| XinZhangMS | 0:f7f1f0d76dd6 | 114 | // fall through |
| XinZhangMS | 0:f7f1f0d76dd6 | 115 | case 3: |
| XinZhangMS | 0:f7f1f0d76dd6 | 116 | pos5 |= ((iterator[2] & 0x0f) << 1); |
| XinZhangMS | 0:f7f1f0d76dd6 | 117 | pos4 = ((iterator[2] & 0xf0) >> 4); |
| XinZhangMS | 0:f7f1f0d76dd6 | 118 | // fall through |
| XinZhangMS | 0:f7f1f0d76dd6 | 119 | case 2: |
| XinZhangMS | 0:f7f1f0d76dd6 | 120 | pos4 |= ((iterator[1] & 0x01) << 4); |
| XinZhangMS | 0:f7f1f0d76dd6 | 121 | pos3 = ((iterator[1] & 0x3e) >> 1); |
| XinZhangMS | 0:f7f1f0d76dd6 | 122 | pos2 = ((iterator[1] & 0xc0) >> 6); |
| XinZhangMS | 0:f7f1f0d76dd6 | 123 | // fall through |
| XinZhangMS | 0:f7f1f0d76dd6 | 124 | case 1: |
| XinZhangMS | 0:f7f1f0d76dd6 | 125 | pos2 |= ((iterator[0] & 0x07) << 2); |
| XinZhangMS | 0:f7f1f0d76dd6 | 126 | pos1 = ((iterator[0] & 0xf8) >> 3); |
| XinZhangMS | 0:f7f1f0d76dd6 | 127 | break; |
| XinZhangMS | 0:f7f1f0d76dd6 | 128 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 129 | // Move the iterator the block size |
| XinZhangMS | 0:f7f1f0d76dd6 | 130 | iterator += block_len; |
| XinZhangMS | 0:f7f1f0d76dd6 | 131 | // and decrement the src_size; |
| XinZhangMS | 0:f7f1f0d76dd6 | 132 | src_size -= block_len; |
| XinZhangMS | 0:f7f1f0d76dd6 | 133 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 134 | /* Codes_SRS_BASE32_07_012: [ If the src_size is not divisible by 8, base32_encode_impl shall pad the remaining places with =. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 135 | switch (block_len) |
| XinZhangMS | 0:f7f1f0d76dd6 | 136 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 137 | case 1: pos3 = pos4 = 32; // fall through |
| XinZhangMS | 0:f7f1f0d76dd6 | 138 | case 2: pos5 = 32; // fall through |
| XinZhangMS | 0:f7f1f0d76dd6 | 139 | case 3: pos6 = pos7 = 32; // fall through |
| XinZhangMS | 0:f7f1f0d76dd6 | 140 | case 4: pos8 = 32; // fall through |
| XinZhangMS | 0:f7f1f0d76dd6 | 141 | case 5: |
| XinZhangMS | 0:f7f1f0d76dd6 | 142 | break; |
| XinZhangMS | 0:f7f1f0d76dd6 | 143 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 144 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 145 | /* Codes_SRS_BASE32_07_011: [ base32_encode_impl shall then map the 5 bit chunks into one of the BASE32 values (a-z,2,3,4,5,6,7) values. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 146 | result[result_len++] = BASE32_VALUES[pos1]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 147 | result[result_len++] = BASE32_VALUES[pos2]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 148 | result[result_len++] = BASE32_VALUES[pos3]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 149 | result[result_len++] = BASE32_VALUES[pos4]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 150 | result[result_len++] = BASE32_VALUES[pos5]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 151 | result[result_len++] = BASE32_VALUES[pos6]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 152 | result[result_len++] = BASE32_VALUES[pos7]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 153 | result[result_len++] = BASE32_VALUES[pos8]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 154 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 155 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 156 | return result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 157 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 158 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 159 | static BUFFER_HANDLE base32_decode_impl(const char* source) |
| XinZhangMS | 0:f7f1f0d76dd6 | 160 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 161 | BUFFER_HANDLE result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 162 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 163 | size_t src_length = strlen(source); |
| XinZhangMS | 0:f7f1f0d76dd6 | 164 | if (src_length % BASE32_INPUT_SIZE != 0) |
| XinZhangMS | 0:f7f1f0d76dd6 | 165 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 166 | /* Codes_SRS_BASE32_07_021: [ If the source length is not evenly divisible by 8, base32_decode_impl shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 167 | LogError("Failure invalid input length %lu", src_length); |
| XinZhangMS | 0:f7f1f0d76dd6 | 168 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 169 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 170 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 171 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 172 | size_t dest_size = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 173 | unsigned char* temp_buffer; |
| XinZhangMS | 0:f7f1f0d76dd6 | 174 | unsigned char* dest_buff; |
| XinZhangMS | 0:f7f1f0d76dd6 | 175 | bool continue_processing = true; |
| XinZhangMS | 0:f7f1f0d76dd6 | 176 | unsigned char input[8]; |
| XinZhangMS | 0:f7f1f0d76dd6 | 177 | const char* iterator = source; |
| XinZhangMS | 0:f7f1f0d76dd6 | 178 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 179 | /* Codes_SRS_BASE32_07_022: [ base32_decode_impl shall allocate a temp buffer to store the in process value. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 180 | size_t allocation_len = base32_decoding_length(src_length); |
| XinZhangMS | 0:f7f1f0d76dd6 | 181 | if ((temp_buffer = (unsigned char*)malloc(allocation_len)) == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 182 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 183 | /* Codes_SRS_BASE32_07_023: [ If an error is encountered, base32_decode_impl shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 184 | LogError("Failure allocating buffer"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 185 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 186 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 187 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 188 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 189 | dest_buff = temp_buffer; |
| XinZhangMS | 0:f7f1f0d76dd6 | 190 | while (*iterator != '\0') |
| XinZhangMS | 0:f7f1f0d76dd6 | 191 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 192 | size_t index = 0; |
| XinZhangMS | 0:f7f1f0d76dd6 | 193 | /* Codes_SRS_BASE32_07_024: [ base32_decode_impl shall loop through and collect 8 characters from the source variable. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 194 | for (index = 0; index < BASE32_INPUT_SIZE; index++) |
| XinZhangMS | 0:f7f1f0d76dd6 | 195 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 196 | input[index] = *iterator; |
| XinZhangMS | 0:f7f1f0d76dd6 | 197 | iterator++; |
| XinZhangMS | 0:f7f1f0d76dd6 | 198 | if (input[index] >= ASCII_VALUE_MAX) |
| XinZhangMS | 0:f7f1f0d76dd6 | 199 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 200 | LogError("Failure source encoding"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 201 | continue_processing = false; |
| XinZhangMS | 0:f7f1f0d76dd6 | 202 | break; |
| XinZhangMS | 0:f7f1f0d76dd6 | 203 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 204 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 205 | input[index] = convert_value_to_base32_char(input[index]); |
| XinZhangMS | 0:f7f1f0d76dd6 | 206 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 207 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 208 | if (!continue_processing) |
| XinZhangMS | 0:f7f1f0d76dd6 | 209 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 210 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 211 | break; |
| XinZhangMS | 0:f7f1f0d76dd6 | 212 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 213 | else if ((dest_size + TARGET_BLOCK_SIZE) > allocation_len) |
| XinZhangMS | 0:f7f1f0d76dd6 | 214 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 215 | LogError("Failure target length exceeded"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 216 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 217 | continue_processing = false; |
| XinZhangMS | 0:f7f1f0d76dd6 | 218 | break; |
| XinZhangMS | 0:f7f1f0d76dd6 | 219 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 220 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 221 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 222 | // Codes_SRS_BASE32_07_025: [ base32_decode_impl shall group 5 bytes at a time into the temp buffer. ] |
| XinZhangMS | 0:f7f1f0d76dd6 | 223 | *dest_buff++ = ((input[0] & 0x1f) << 3) | ((input[1] & 0x1c) >> 2); |
| XinZhangMS | 0:f7f1f0d76dd6 | 224 | *dest_buff++ = ((input[1] & 0x03) << 6) | ((input[2] & 0x1f) << 1) | ((input[3] & 0x10) >> 4); |
| XinZhangMS | 0:f7f1f0d76dd6 | 225 | *dest_buff++ = ((input[3] & 0x0f) << 4) | ((input[4] & 0x1e) >> 1); |
| XinZhangMS | 0:f7f1f0d76dd6 | 226 | *dest_buff++ = ((input[4] & 0x01) << 7) | ((input[5] & 0x1f) << 2) | ((input[6] & 0x18) >> 3); |
| XinZhangMS | 0:f7f1f0d76dd6 | 227 | *dest_buff++ = ((input[6] & 0x07) << 5) | (input[7] & 0x1f); |
| XinZhangMS | 0:f7f1f0d76dd6 | 228 | dest_size += TARGET_BLOCK_SIZE; |
| XinZhangMS | 0:f7f1f0d76dd6 | 229 | // If there is padding remove it |
| XinZhangMS | 0:f7f1f0d76dd6 | 230 | // Because we are packing 5 bytes into an 8 byte variable we need to check every other |
| XinZhangMS | 0:f7f1f0d76dd6 | 231 | // variable for padding |
| XinZhangMS | 0:f7f1f0d76dd6 | 232 | if (input[7] == BASE32_EQUAL_SIGN) |
| XinZhangMS | 0:f7f1f0d76dd6 | 233 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 234 | --dest_size; |
| XinZhangMS | 0:f7f1f0d76dd6 | 235 | if (input[5] == BASE32_EQUAL_SIGN) |
| XinZhangMS | 0:f7f1f0d76dd6 | 236 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 237 | --dest_size; |
| XinZhangMS | 0:f7f1f0d76dd6 | 238 | if (input[4] == BASE32_EQUAL_SIGN) |
| XinZhangMS | 0:f7f1f0d76dd6 | 239 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 240 | --dest_size; |
| XinZhangMS | 0:f7f1f0d76dd6 | 241 | if (input[2] == BASE32_EQUAL_SIGN) |
| XinZhangMS | 0:f7f1f0d76dd6 | 242 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 243 | --dest_size; |
| XinZhangMS | 0:f7f1f0d76dd6 | 244 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 245 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 246 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 247 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 248 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 249 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 250 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 251 | if (!continue_processing) |
| XinZhangMS | 0:f7f1f0d76dd6 | 252 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 253 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 254 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 255 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 256 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 257 | /* Codes_SRS_BASE32_07_026: [ Once base32_decode_impl is complete it shall create a BUFFER with the temp buffer. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 258 | result = BUFFER_create(temp_buffer, dest_size); |
| XinZhangMS | 0:f7f1f0d76dd6 | 259 | if (result == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 260 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 261 | LogError("Failure: BUFFER_create failed to create decoded buffer"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 262 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 263 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 264 | free(temp_buffer); |
| XinZhangMS | 0:f7f1f0d76dd6 | 265 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 266 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 267 | return result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 268 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 269 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 270 | BUFFER_HANDLE Base32_Decode(STRING_HANDLE handle) |
| XinZhangMS | 0:f7f1f0d76dd6 | 271 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 272 | BUFFER_HANDLE result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 273 | if (handle == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 274 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 275 | /* Codes_SRS_BASE32_07_016: [ If source is NULL Base32_Decoder shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 276 | LogError("invalid parameter handle"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 277 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 278 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 279 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 280 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 281 | const char* str_source = STRING_c_str(handle); |
| XinZhangMS | 0:f7f1f0d76dd6 | 282 | if (str_source == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 283 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 284 | /* Codes_SRS_BASE32_07_027: [ If the string in source value is NULL, Base32_Decoder shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 285 | LogError("NULL value specified in string"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 286 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 287 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 288 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 289 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 290 | /* Codes_SRS_BASE32_07_018: [ Base32_Decoder shall call base32_decode_impl to decode the base64 value. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 291 | result = base32_decode_impl(str_source); |
| XinZhangMS | 0:f7f1f0d76dd6 | 292 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 293 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 294 | /* Codes_SRS_BASE32_07_017: [ On success Base32_Decoder shall return a BUFFER_HANDLE that contains the decoded bytes for source. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 295 | return result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 296 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 297 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 298 | BUFFER_HANDLE Base32_Decode_String(const char* source) |
| XinZhangMS | 0:f7f1f0d76dd6 | 299 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 300 | BUFFER_HANDLE result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 301 | if (source == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 302 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 303 | /* Codes_SRS_BASE32_07_008: [ If source is NULL Base32_Decoder_String shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 304 | LogError("invalid parameter source=NULL"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 305 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 306 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 307 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 308 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 309 | /* Codes_SRS_BASE32_07_020: [ Base32_Decoder_String shall call base32_decode_impl to decode the base64 value. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 310 | result = base32_decode_impl(source); |
| XinZhangMS | 0:f7f1f0d76dd6 | 311 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 312 | /* Codes_SRS_BASE32_07_019: [ On success Base32_Decoder_String shall return a BUFFER_HANDLE that contains the decoded bytes for source. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 313 | return result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 314 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 315 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 316 | char* Base32_Encode_Bytes(const unsigned char* source, size_t size) |
| XinZhangMS | 0:f7f1f0d76dd6 | 317 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 318 | char* result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 319 | if (source == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 320 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 321 | /* Codes_SRS_BASE32_07_004: [ If source is NULL Base32_Encode shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 322 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 323 | LogError("Failure: Invalid input parameter source"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 324 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 325 | else if (size == 0) |
| XinZhangMS | 0:f7f1f0d76dd6 | 326 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 327 | /* Codes_SRS_BASE32_07_005: [ If size is 0 Base32_Encode shall return an empty string. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 328 | result = malloc(1); |
| XinZhangMS | 0:f7f1f0d76dd6 | 329 | strcpy(result, ""); |
| XinZhangMS | 0:f7f1f0d76dd6 | 330 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 331 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 332 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 333 | /* Codes_SRS_BASE32_07_007: [ Base32_Encode_Bytes shall call into base32_Encode_impl to encode the source data. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 334 | result = base32_encode_impl(source, size); |
| XinZhangMS | 0:f7f1f0d76dd6 | 335 | if (result == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 336 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 337 | /* Codes_SRS_BASE32_07_014: [ Upon failure Base32_Encode_Bytes shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 338 | LogError("encoding of unsigned char failed."); |
| XinZhangMS | 0:f7f1f0d76dd6 | 339 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 340 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 341 | /* Codes_SRS_BASE32_07_006: [ If successful Base32_Encode shall return the base32 value of input. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 342 | return result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 343 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 344 | |
| XinZhangMS | 0:f7f1f0d76dd6 | 345 | STRING_HANDLE Base32_Encode(BUFFER_HANDLE source) |
| XinZhangMS | 0:f7f1f0d76dd6 | 346 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 347 | STRING_HANDLE result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 348 | if (source == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 349 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 350 | /* Codes_SRS_BASE32_07_001: [ If source is NULL Base32_Encode shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 351 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 352 | LogError("Failure: Invalid input parameter"); |
| XinZhangMS | 0:f7f1f0d76dd6 | 353 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 354 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 355 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 356 | size_t input_len = BUFFER_length(source); |
| XinZhangMS | 0:f7f1f0d76dd6 | 357 | const unsigned char* input_value = BUFFER_u_char(source); |
| XinZhangMS | 0:f7f1f0d76dd6 | 358 | if (input_value == NULL || input_len == 0) |
| XinZhangMS | 0:f7f1f0d76dd6 | 359 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 360 | /* Codes_SRS_BASE32_07_015: [ If size is 0 Base32_Encode shall return an empty string. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 361 | result = STRING_new(); |
| XinZhangMS | 0:f7f1f0d76dd6 | 362 | if (result == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 363 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 364 | LogError("Failure constructing new string."); |
| XinZhangMS | 0:f7f1f0d76dd6 | 365 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 366 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 367 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 368 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 369 | /* Codes_SRS_BASE32_07_003: [ Base32_Encode shall call into base32_Encode_impl to encode the source data. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 370 | char* encoded = base32_encode_impl(input_value, input_len); |
| XinZhangMS | 0:f7f1f0d76dd6 | 371 | if (encoded == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 372 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 373 | /* Codes_SRS_BASE32_07_014: [ Upon failure base32_Encode shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 374 | LogError("base32 encode implementation failed."); |
| XinZhangMS | 0:f7f1f0d76dd6 | 375 | result = NULL; |
| XinZhangMS | 0:f7f1f0d76dd6 | 376 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 377 | else |
| XinZhangMS | 0:f7f1f0d76dd6 | 378 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 379 | /* Codes_SRS_BASE32_07_012: [ base32_Encode shall wrap the base32_Encode_impl result into a STRING_HANDLE. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 380 | result = STRING_construct(encoded); |
| XinZhangMS | 0:f7f1f0d76dd6 | 381 | if (result == NULL) |
| XinZhangMS | 0:f7f1f0d76dd6 | 382 | { |
| XinZhangMS | 0:f7f1f0d76dd6 | 383 | /* Codes_SRS_BASE32_07_014: [ Upon failure base32_Encode shall return NULL. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 384 | LogError("string construction failed."); |
| XinZhangMS | 0:f7f1f0d76dd6 | 385 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 386 | free(encoded); |
| XinZhangMS | 0:f7f1f0d76dd6 | 387 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 388 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 389 | } |
| XinZhangMS | 0:f7f1f0d76dd6 | 390 | /* Codes_SRS_BASE32_07_002: [ If successful Base32_Encode shall return the base32 value of source. ] */ |
| XinZhangMS | 0:f7f1f0d76dd6 | 391 | return result; |
| XinZhangMS | 0:f7f1f0d76dd6 | 392 | } |