1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdint.h>
12
13 #include <openssl/evp.h>
14 #include <openssl/bio.h>
15 #include "common_crypto_encode.h"
16 #include "common_util_log.h"
17
18
19 /* header and footer of the PEM */
20 #define CC_UTIL_COMMON_PEM_HEADER "-----BEGIN CERTIFICATE-----"
21 #define CC_UTIL_COMMON_PEM_FOOTER "-----END CERTIFICATE-----"
22
23
24 #define IS_BASE64_ENCODE_VAL(val) \
25 ((((val >= '0') && (val <= '9')) || \
26 ((val >= 'A') && (val <= 'Z')) || \
27 ((val >= 'a') && (val <= 'z')) || \
28 (val == '+') || (val == '/'))?1:0)
29
30 /**
31 * @brief Encodes data into base64 format
32 *
33 * @param[in] pBuff - the buffer to encode
34 * @param[in] buffLen - input buffer length
35 * @param[out] pEncBuff - encoded buffer
36 * @param[in/out] pEncBuffLen - encoded buffer length
37 */
38 /*********************************************************/
CC_CommonBase64Encode(uint8_t * pBuff,uint32_t buffLen,uint8_t * pEncBuff,uint32_t * pEecBuffLen)39 int32_t CC_CommonBase64Encode(uint8_t *pBuff,
40 uint32_t buffLen,
41 uint8_t *pEncBuff,
42 uint32_t *pEecBuffLen)
43 {
44 BIO *bio = NULL;
45 BIO *b64 = NULL;;
46 size_t size;
47 FILE *stream = NULL;
48 int32_t actualWritten = 0;
49 int32_t rc = 0;
50
51 if ((NULL == pBuff) ||
52 (NULL == pEncBuff) ||
53 (NULL == pEecBuffLen) ||
54 (0 == buffLen)) {
55 UTIL_LOG_ERR("ilegal inputs\n");
56 return 1;
57 }
58 if (*pEecBuffLen < ((((buffLen*4)+2)/3)+1)) {
59 UTIL_LOG_ERR("ilegal outBuffLen %d \n", *pEecBuffLen);
60 return 1;
61 }
62
63 memset(pEncBuff, 0, *pEecBuffLen);
64
65 stream = fmemopen(pEncBuff, *pEecBuffLen, "w");
66 if (NULL == stream) {
67 UTIL_LOG_ERR("failed to open mem\n");
68 return 1;
69 }
70 b64 = BIO_new(BIO_f_base64());
71 if (NULL == b64) {
72 UTIL_LOG_ERR("failed to BIO_new\n");
73 rc = 1;
74 goto End_Base64Encode;
75 }
76 bio = BIO_new_fp(stream, BIO_NOCLOSE);
77 if (NULL == bio) {
78 UTIL_LOG_ERR("failed to BIO_new_fp\n");
79 rc = 1;
80 goto End_Base64Encode;
81 }
82 bio = BIO_push(b64, bio);
83 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line
84 actualWritten = BIO_write(bio, pBuff, buffLen);
85 BIO_flush(bio);
86 if (actualWritten != buffLen) {
87 UTIL_LOG_ERR("failed to BIO_write buffLen %d = actualWritten %d\n", buffLen, actualWritten);
88 rc = 1;
89 goto End_Base64Encode;
90 }
91 rc = 0;
92
93 End_Base64Encode:
94 if (bio != NULL) { /* clears bio and b64, b64 mustn't clear explicitly*/
95 BIO_free_all(bio);
96 }
97 if (stream != NULL) {
98 fclose(stream);
99 }
100 return rc;
101 }
102
103
104 /**
105 * @brief Decode base64-encoded data
106 *
107 * @param[in] pEncBuff - base64-encoded buffer
108 * @param[in] encBuffLen - input buffer length
109 * @param[out] pDecBuff - decoded buffer
110 * @param[in/out] pDecBuffLen - decoded buffer length
111 */
112 /*********************************************************/
CC_CommonBase64Decode(uint8_t * pEncBuff,uint32_t encBuffLen,uint8_t * pDecBuff,uint32_t * pDecBuffLen)113 int32_t CC_CommonBase64Decode(uint8_t *pEncBuff,
114 uint32_t encBuffLen,
115 uint8_t *pDecBuff,
116 uint32_t *pDecBuffLen)
117 {
118 BIO *bio = NULL;
119 BIO *b64 = NULL;
120 int32_t actualRead = 0;
121 int32_t expDecBuffLen = 0;
122 FILE* stream = NULL;
123 int32_t padding = 0;
124 int32_t rc = 0;
125 int32_t i = 0;
126
127 if ((NULL == pEncBuff) ||
128 (NULL == pDecBuff) ||
129 (NULL == pDecBuffLen) ||
130 (0 == encBuffLen)) {
131 UTIL_LOG_ERR("ilegal inputs\n");
132 return 1;
133 }
134
135 UTIL_LOG_INFO("started. encBuffLen %d\n", encBuffLen);
136 /* check validity of decoded buffer length */
137 i = encBuffLen-1;
138 while (!IS_BASE64_ENCODE_VAL(pEncBuff[i])) {
139 UTIL_LOG_INFO("pEncBuff[%d] 0x%x\n", i, pEncBuff[i]);
140 padding++;
141 i--;
142 }
143 expDecBuffLen = (((encBuffLen-padding)*3)/4);
144 if (*pDecBuffLen < expDecBuffLen) {
145 UTIL_LOG_ERR("ilegal inputs outBuffLen %d expDecBuffLen %d\n", *pDecBuffLen, expDecBuffLen);
146 rc = 1;
147 goto End_Base64Decode;
148 }
149
150 memset(pDecBuff, 0, *pDecBuffLen);
151
152 stream = fmemopen(pEncBuff, encBuffLen, "r");
153 if (NULL == stream) {
154 UTIL_LOG_ERR("failed to open mem\n");
155 rc = 1;
156 goto End_Base64Decode;
157 }
158
159 b64 = BIO_new(BIO_f_base64());
160 if (NULL == b64) {
161 UTIL_LOG_ERR("failed to BIO_new\n");
162 rc = 1;
163 goto End_Base64Decode;
164 }
165 bio = BIO_new_fp(stream, BIO_NOCLOSE);
166 if (NULL == bio) {
167 UTIL_LOG_ERR("failed to BIO_new_fp\n");
168 rc = 1;
169 goto End_Base64Decode;
170 }
171 bio = BIO_push(b64, bio);
172 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
173 actualRead = BIO_read(bio, pDecBuff, encBuffLen);
174 if (actualRead != expDecBuffLen) {
175 UTIL_LOG_ERR("failed to BIO_read expDecBuffLen %d = actualRead %d\n", expDecBuffLen, actualRead);
176 rc = 1;
177 goto End_Base64Decode;
178 }
179 *pDecBuffLen = actualRead;
180 rc = 0;
181
182 End_Base64Decode:
183 if (bio != NULL) { /* clears bio and b64, b64 mustn't clear explicitly*/
184 BIO_free_all(bio);
185 }
186 if (stream != NULL) {
187 fclose(stream);
188 }
189 UTIL_LOG_INFO("rc %d\n", rc);
190 return rc;
191 }
192
193